tôi muốn chạy file sql-vew_smart_home như sql-vie
- Sao chép liên kết
- Chia sẻ với Facebook
- Chia sẻ với X
- Chia sẻ với Pinterest
- Chia sẻ với Linkedin
- Gửi bài qua Email
gửi email cho tác giả
tôi muốn chạy file sql-vew_smart_home như sql-view nhưng là địa chỉ Channel1.UA.23_dien_nang_tieu_thu_nam_hue_huong(kwh)_UA nhé. địa chỉ này lưu trong sql server. sql-view.ejs chạy ok rồi. giờ thêm sql-view_smart_home
ChatGPT đã nói:
Mình đã xem code bạn gửi, hiện tại:
-
/sql-view
đã hoạt động tốt với filesql-view.ejs
sql-view
.
-
Bạn đã có file
sql-view_smart_home.ejs
riêngsql-view_smart_home
nhưng trong
index.js
chưa có route xử lý cho nó. -
/sql-production
trongindex.js
đang fix cứngtagName = "Channel1.UA.7_san_luong_Nam_MHP(Mwh)_UA"
index
.
👉 Để chạy được sql-view_smart_home
với tag "Channel1.UA.23_dien_nang_tieu_thu_nam_hue_huong(kwh)_UA"
, bạn cần thêm route mới trong index.js
tương tự như /sql-view
, nhưng render ra sql-view_smart_home.ejs
và mặc định lấy đúng địa chỉ đó.
Ví dụ sửa trong index.js
:
// =================== SQL-VIEW SMART HOME ===================
app.get("/sql-view_smart_home", async (req, res) => {
try {
const deviceName = req.query.name || "Channel1.UA.23_dien_nang_tieu_thu_nam_hue_huong(kwh)_UA";
const timeStart = toSqlDateTime(req.query.start || "2025-09-06T00:00");
const timeEnd = toSqlDateTime(req.query.end || "2025-09-06T23:59");
let pool = await sql.connect({
user: "sa",
password: "123456",
server: "SERVER",
database: "da_test",
options: { encrypt: false, trustServerCertificate: true, port: 49751 }
});
const result = await pool.request().query(`
SELECT TOP (1000)
[id],
[_NAME],
[_NUMERICID],
[_VALUE],
CONVERT(varchar, [_TIMESTAMP], 120) AS TS,
[_QUALITY]
FROM [da_test].[dbo].[test_node_js]
WHERE [_NAME] = '${deviceName}'
AND [_TIMESTAMP] BETWEEN '${timeStart}' AND '${timeEnd}'
ORDER BY [_TIMESTAMP]
`);
const names = await pool.request().query(`
SELECT DISTINCT [_NAME] as name
FROM [da_test].[dbo].[test_node_js]
ORDER BY name
`);
const records = result.recordset || [];
// === Phân tích dữ liệu ===
let analysis = {};
if (records.length > 0) {
const values = records.map(r => Number(r._VALUE)).filter(v => !isNaN(v));
const qualities = records.map(r => r._QUALITY);
analysis.count = records.length;
analysis.min = Math.min(...values);
analysis.max = Math.max(...values);
analysis.avg = values.reduce((a,b)=>a+b,0)/values.length;
const goodCount = qualities.filter(q => q === 192).length;
analysis.goodPercent = (goodCount / qualities.length * 100).toFixed(2);
} else {
analysis = { count: 0, min: "-", max: "-", avg: "-", goodPercent: "-" };
}
res.render("sql-view_smart_home", {
data: records,
deviceName,
deviceNames: [deviceName],
timeRange: `${timeStart} → ${timeEnd}`,
allNames: names.recordset,
analysis,
aiResult: null
});
} catch (err) {
console.error("❌ SQL Smart Home Error:", err);
res.status(500).send("SQL query failed: " + err.message);
}
});
✅ Sau khi thêm đoạn này, bạn mở trên trình duyệt:
http://192.168.100.197:3000/sql-view_smart_home
Trang sẽ chạy giống sql-view
nhưng mặc định lấy dữ liệu từ tag Channel1.UA.23_dien_nang_tieu_thu_nam_hue_huong(kwh)_UA
.
Bạn có muốn mình chỉnh luôn /sql-production
để dùng tag riêng cho smart_home (ví dụ /sql-production_smart_home
) không?
Bạn đã nói:
ChatGPT đã nói:
Có bạn nhé 👍.
Hiện tại /sql-production
đang fix cứng tagName = "Channel1.UA.7_san_luong_Nam_MHP(Mwh)_UA"
index
.
Nếu bạn muốn tính sản lượng cho smart home thì cần thêm một API tương tự nhưng đổi sang tag:
Channel1.UA.23_dien_nang_tieu_thu_nam_hue_huong(kwh)_UA
👉 Thêm route mới trong index.js
:
// =================== SQL-PRODUCTION SMART HOME ===================
app.get("/sql-production_smart_home", async (req, res) => {
try {
let pool = await sql.connect({
user: "sa",
password: "123456",
server: "SERVER",
database: "da_test",
options: { encrypt: false, trustServerCertificate: true, port: 49751 }
});
const tagName = "Channel1.UA.23_dien_nang_tieu_thu_nam_hue_huong(kwh)_UA";
// === Sản lượng ngày ===
const daily = await pool.request().query(`
WITH daily_cte AS (
SELECT
CAST(_TIMESTAMP AS DATE) AS Ngay,
TRY_CONVERT(float, REPLACE(REPLACE(_VALUE, 'kWh', ''), ',', '.')) AS val,
_TIMESTAMP,
ROW_NUMBER() OVER (
PARTITION BY CAST(_TIMESTAMP AS DATE)
ORDER BY _TIMESTAMP ASC
) AS rn_asc,
ROW_NUMBER() OVER (
PARTITION BY CAST(_TIMESTAMP AS DATE)
ORDER BY _TIMESTAMP DESC
) AS rn_desc
FROM dbo.test_node_js
WHERE _NAME = '${tagName}'
)
SELECT
Ngay,
MAX(CASE WHEN rn_asc = 1 THEN val END) AS GiaTriDau,
MAX(CASE WHEN rn_desc = 1 THEN val END) AS GiaTriCuoi,
MAX(CASE WHEN rn_desc = 1 THEN val END) -
MAX(CASE WHEN rn_asc = 1 THEN val END) AS SanLuong
FROM daily_cte
GROUP BY Ngay
ORDER BY Ngay;
`);
// === Sản lượng tháng ===
const monthly = await pool.request().query(`
WITH cte AS (
SELECT YEAR(_TIMESTAMP) AS Nam, MONTH(_TIMESTAMP) AS Thang,
TRY_CONVERT(float, REPLACE(REPLACE(_VALUE, 'kWh', ''), ',', '.')) AS val,
_TIMESTAMP,
ROW_NUMBER() OVER (PARTITION BY YEAR(_TIMESTAMP), MONTH(_TIMESTAMP) ORDER BY _TIMESTAMP ASC) rn_asc,
ROW_NUMBER() OVER (PARTITION BY YEAR(_TIMESTAMP), MONTH(_TIMESTAMP) ORDER BY _TIMESTAMP DESC) rn_desc
FROM dbo.test_node_js
WHERE _NAME = '${tagName}'
)
SELECT Nam, Thang,
MAX(CASE WHEN rn_asc = 1 THEN val END) AS GiaTriDau,
MAX(CASE WHEN rn_desc = 1 THEN val END) AS GiaTriCuoi,
MAX(CASE WHEN rn_desc = 1 THEN val END) -
MAX(CASE WHEN rn_asc = 1 THEN val END) AS SanLuong
FROM cte
GROUP BY Nam, Thang
ORDER BY Nam, Thang;
`);
// === Sản lượng quý ===
const quarterly = await pool.request().query(`
WITH cte AS (
SELECT YEAR(_TIMESTAMP) AS Nam, DATEPART(QUARTER, _TIMESTAMP) AS Quy,
TRY_CONVERT(float, REPLACE(REPLACE(_VALUE, 'kWh', ''), ',', '.')) AS val,
_TIMESTAMP,
ROW_NUMBER() OVER (PARTITION BY YEAR(_TIMESTAMP), DATEPART(QUARTER, _TIMESTAMP) ORDER BY _TIMESTAMP ASC) rn_asc,
ROW_NUMBER() OVER (PARTITION BY YEAR(_TIMESTAMP), DATEPART(QUARTER, _TIMESTAMP) ORDER BY _TIMESTAMP DESC) rn_desc
FROM dbo.test_node_js
WHERE _NAME = '${tagName}'
)
SELECT Nam, Quy,
MAX(CASE WHEN rn_asc = 1 THEN val END) AS GiaTriDau,
MAX(CASE WHEN rn_desc = 1 THEN val END) AS GiaTriCuoi,
MAX(CASE WHEN rn_desc = 1 THEN val END) -
MAX(CASE WHEN rn_asc = 1 THEN val END) AS SanLuong
FROM cte
GROUP BY Nam, Quy
ORDER BY Nam, Quy;
`);
// === Sản lượng năm ===
const yearly = await pool.request().query(`
WITH cte AS (
SELECT YEAR(_TIMESTAMP) AS Nam,
TRY_CONVERT(float, REPLACE(REPLACE(_VALUE, 'kWh', ''), ',', '.')) AS val,
_TIMESTAMP,
ROW_NUMBER() OVER (PARTITION BY YEAR(_TIMESTAMP) ORDER BY _TIMESTAMP ASC) rn_asc,
ROW_NUMBER() OVER (PARTITION BY YEAR(_TIMESTAMP) ORDER BY _TIMESTAMP DESC) rn_desc
FROM dbo.test_node_js
WHERE _NAME = '${tagName}'
)
SELECT Nam,
MAX(CASE WHEN rn_asc = 1 THEN val END) AS GiaTriDau,
MAX(CASE WHEN rn_desc = 1 THEN val END) AS GiaTriCuoi,
MAX(CASE WHEN rn_desc = 1 THEN val END) -
MAX(CASE WHEN rn_asc = 1 THEN val END) AS SanLuong
FROM cte
GROUP BY Nam
ORDER BY Nam;
`);
res.json({
daily: daily.recordset,
monthly: monthly.recordset,
quarterly: quarterly.recordset,
yearly: yearly.recordset
});
} catch (err) {
console.error("❌ SQL Production Smart Home Error:", err);
res.status(500).send("Lỗi: " + err.message);
}
});
✅ Vậy bạn sẽ có 2 API:
-
/sql-production
→ dùng cho MHP (MWh). -
/sql-production_smart_home
→ dùng cho Smart Home (kWh).
👉 Trong file sql-view_smart_home.ejs
, bạn chỉ cần đổi các chỗ gọi $.get("/sql-production", ...)
thành $.get("/sql-production_smart_home", ...)
.
Bạn có muốn mình chỉnh sẵn file sql-view_smart_home.ejs
để gọi đúng API mới không?