Files
EMS-ESP32/mock-api/server.js
2021-06-14 21:28:20 +02:00

974 lines
19 KiB
JavaScript

const express = require('express')
const path = require('path')
const msgpack = require('@msgpack/msgpack')
// REST API
const app = express()
const port = process.env.PORT || 3080
const REST_ENDPOINT_ROOT = '/rest/'
app.use(express.static(path.join(__dirname, '../interface/build')))
app.use(express.json())
// ES API
const server = express()
const es_port = 3090
const ES_ENDPOINT_ROOT = '/es/'
// NTP
const NTP_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'ntpStatus'
const NTP_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'ntpSettings'
const TIME_ENDPOINT = REST_ENDPOINT_ROOT + 'time'
const ntp_settings = {
enabled: true,
server: 'time.google.com',
tz_label: 'Europe/Amsterdam',
tz_format: 'CET-1CEST,M3.5.0,M10.5.0/3',
}
const ntp_status = {
status: 1,
utc_time: '2021-04-01T14:25:42Z',
local_time: '2021-04-01T16:25:42',
server: 'time.google.com',
uptime: 856,
}
// AP
const AP_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'apSettings'
const AP_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'apStatus'
const ap_settings = {
provision_mode: 1,
ssid: 'ems-esp',
password: 'ems-esp-neo',
local_ip: '192.168.4.1',
gateway_ip: '192.168.4.1',
subnet_mask: '255.255.255.0',
}
const ap_status = {
status: 1,
ip_address: '192.168.4.1',
mac_address: '3C:61:05:03:AB:2D',
station_num: 0,
}
// NETWORK
const NETWORK_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'networkSettings'
const NETWORK_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'networkStatus'
const SCAN_NETWORKS_ENDPOINT = REST_ENDPOINT_ROOT + 'scanNetworks'
const LIST_NETWORKS_ENDPOINT = REST_ENDPOINT_ROOT + 'listNetworks'
const network_settings = {
ssid: 'myWifi',
password: 'myPassword',
hostname: 'ems-esp',
static_ip_config: false,
}
const network_status = {
status: 3,
local_ip: '10.10.10.101',
mac_address: '3C:61:05:03:AB:2C',
rssi: -41,
ssid: 'home',
bssid: '06:ED:DA:FE:B4:68',
channel: 11,
subnet_mask: '255.255.255.0',
gateway_ip: '10.10.10.1',
dns_ip_1: '10.10.10.1',
dns_ip_2: '0.0.0.0',
}
const list_networks = {
networks: [
{
rssi: -40,
ssid: '',
bssid: 'FC:EC:DA:FD:B4:68',
channel: 11,
encryption_type: 3,
},
{
rssi: -41,
ssid: 'home',
bssid: '02:EC:DA:FD:B4:68',
channel: 11,
encryption_type: 3,
},
{
rssi: -42,
ssid: '',
bssid: '06:EC:DA:FD:B4:68',
channel: 11,
encryption_type: 3,
},
{
rssi: -73,
ssid: '',
bssid: 'FC:EC:DA:17:D4:7E',
channel: 1,
encryption_type: 3,
},
{
rssi: -73,
ssid: 'office',
bssid: '02:EC:DA:17:D4:7E',
channel: 1,
encryption_type: 3,
},
{
rssi: -75,
ssid: 'Erica',
bssid: 'C8:D7:19:9A:88:BD',
channel: 2,
encryption_type: 3,
},
{
rssi: -75,
ssid: '',
bssid: 'C6:C9:E3:FF:A5:DE',
channel: 2,
encryption_type: 3,
},
{
rssi: -76,
ssid: 'Bruin',
bssid: 'C0:C9:E3:FF:A5:DE',
channel: 2,
encryption_type: 3,
},
],
}
// OTA
const OTA_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'otaSettings'
const ota_settings = {
enabled: true,
port: 8266,
password: 'ems-esp-neo',
}
// MQTT
const MQTT_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'mqttSettings'
const MQTT_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'mqttStatus'
const mqtt_settings = {
enabled: true,
host: '192.168.1.4',
port: 1883,
base: 'ems-esp32',
username: '',
password: '',
client_id: 'ems-esp32',
keep_alive: 60,
clean_session: true,
max_topic_length: 128,
publish_time_boiler: 10,
publish_time_thermostat: 10,
publish_time_solar: 10,
publish_time_mixer: 10,
publish_time_other: 10,
publish_time_sensor: 10,
mqtt_qos: 0,
mqtt_retain: false,
dallas_format: 1,
bool_format: 1,
ha_climate_format: 1,
ha_enabled: true,
nested_format: 1,
subscribe_format: 0,
}
const mqtt_status = {
enabled: true,
connected: true,
client_id: 'ems-esp32',
disconnect_reason: 0,
mqtt_fails: 0,
}
// SYSTEM
const FEATURES_ENDPOINT = REST_ENDPOINT_ROOT + 'features'
const VERIFY_AUTHORIZATION_ENDPOINT = REST_ENDPOINT_ROOT + 'verifyAuthorization'
const SYSTEM_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'systemStatus'
const SECURITY_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'securitySettings'
const RESTART_ENDPOINT = REST_ENDPOINT_ROOT + 'restart'
const FACTORY_RESET_ENDPOINT = REST_ENDPOINT_ROOT + 'factoryReset'
const UPLOAD_FIRMWARE_ENDPOINT = REST_ENDPOINT_ROOT + 'uploadFirmware'
const SIGN_IN_ENDPOINT = REST_ENDPOINT_ROOT + 'signIn'
const GENERATE_TOKEN_ENDPOINT = REST_ENDPOINT_ROOT + 'generateToken'
const system_status = {
emsesp_version: '3.1 demo',
esp_platform: 'ESP32',
max_alloc_heap: 113792,
psram_size: 0,
free_psram: 0,
cpu_freq_mhz: 240,
free_heap: 193340,
sdk_version: 'v3.3.5-1-g85c43024c',
flash_chip_size: 4194304,
flash_chip_speed: 40000000,
fs_total: 65536,
fs_used: 16384,
uptime: '000+00:15:42.707',
}
const security_settings = {
jwt_secret: 'naughty!',
users: [
{ username: 'admin', password: 'admin', admin: true },
{ username: 'guest', password: 'guest', admin: false },
],
}
const features = {
project: true,
security: true,
mqtt: true,
ntp: true,
ota: true,
upload_firmware: true,
}
const verify_authentication = { access_token: '1234' }
const signin = {
access_token:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiYWRtaW4iOnRydWUsInZlcnNpb24iOiIzLjAuMmIwIn0.MsHSgoJKI1lyYz77EiT5ZN3ECMrb4mPv9FNy3udq0TU',
}
const generate_token = { token: '1234' }
// EMS-ESP Project specific
const EMSESP_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'emsespSettings'
const EMSESP_ALLDEVICES_ENDPOINT = REST_ENDPOINT_ROOT + 'allDevices'
const EMSESP_SCANDEVICES_ENDPOINT = REST_ENDPOINT_ROOT + 'scanDevices'
const EMSESP_DEVICEDATA_ENDPOINT = REST_ENDPOINT_ROOT + 'deviceData'
const EMSESP_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'emsespStatus'
const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile'
const WRITE_VALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeValue'
const emsesp_settings = {
tx_mode: 1,
tx_delay: 0,
ems_bus_id: 11,
syslog_enabled: false,
syslog_level: 3,
trace_raw: false,
syslog_mark_interval: 0,
syslog_host: '192.168.1.4',
syslog_port: 514,
master_thermostat: 0,
shower_timer: true,
shower_alert: false,
rx_gpio: 23,
tx_gpio: 5,
dallas_gpio: 3,
dallas_parasite: false,
led_gpio: 2,
hide_led: false,
notoken_api: false,
analog_enabled: false,
pbutton_gpio: 0,
board_profile: 'S32',
}
const emsesp_alldevices = {
devices: [
{
id: 1,
type: 'Thermostat',
brand: '',
name: 'RC20/Moduline 300',
deviceid: 23,
productid: 77,
version: '03.03',
},
{
id: 2,
type: 'Boiler',
brand: 'Nefit',
name: 'GBx72/Trendline/Cerapur/Greenstar Si/27i',
deviceid: 8,
productid: 123,
version: '06.01',
},
{
id: 3,
type: 'Controller',
brand: '',
name: 'BC10',
deviceid: 9,
productid: 190,
version: '01.03',
},
],
sensors: [
{ no: 1, id: '28-233D-9497-0C03', temp: '25.7' },
{ no: 2, id: '28-243D-7437-1E3A', temp: '26.1' },
],
}
const emsesp_status = {
status: 0,
rx_received: 344,
tx_sent: 104,
rx_quality: 100,
tx_quality: 100,
}
const emsesp_devicedata_1 = {
name: 'Thermostat: RC20/Moduline 300',
data: [
{
v: '(0)',
u: 0,
n: 'error code',
c: '',
},
{
v: '14:54:39 06/06/2021',
u: 0,
n: 'date/time',
c: '',
},
{
v: 18,
u: 1,
n: '(hc1) selected room temperature',
c: 'hc1/seltemp',
},
{
v: 22.6,
u: 1,
n: '(hc1) current room temperature',
c: '',
},
{
v: 'auto',
u: 0,
n: '(hc1) mode',
c: 'hc1/mode',
},
],
}
const emsesp_devicedata_2 = {
name: 'Boiler: Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i',
data: [
{
v: false,
u: 16,
n: 'heating active',
c: '',
},
{
v: false,
u: 16,
n: 'warm water active',
c: '',
},
{
v: 5,
u: 1,
n: 'selected flow temperature',
c: 'selflowtemp',
},
{
v: 0,
u: 2,
n: 'burner selected max power',
c: 'selburnpow',
},
{
v: 0,
u: 2,
n: 'heating pump modulation',
c: '',
},
{
v: 51,
u: 1,
n: 'current flow temperature',
c: '',
},
{
v: 49.8,
u: 1,
n: 'return temperature',
c: '',
},
{
v: 1.1,
u: 9,
n: 'system pressure',
c: '',
},
{
v: 52.7,
u: 1,
n: 'boiler temperature',
c: '',
},
{
v: false,
u: 16,
n: 'gas',
c: '',
},
{
v: 0,
u: 8,
n: 'flame current',
c: '',
},
{
v: false,
u: 16,
n: 'heating pump',
c: '',
},
{
v: false,
u: 16,
n: 'fan',
c: '',
},
{
v: false,
u: 16,
n: 'ignition',
c: '',
},
{
v: true,
u: 16,
n: 'heating activated',
c: 'heatingactivated',
},
{
v: 75,
u: 1,
n: 'heating temperature',
c: 'heatingtemp',
},
{
v: 90,
u: 2,
n: 'burner pump max power',
c: 'pumpmodmax',
},
{
v: 55,
u: 2,
n: 'burner pump min power',
c: 'pumpmodmin',
},
{
v: 1,
u: 7,
n: 'pump delay',
c: 'pumpdelay',
},
{
v: 10,
u: 7,
n: 'burner min period',
c: 'burnminperiod',
},
{
v: 0,
u: 2,
n: 'burner min power',
c: 'burnminpower',
},
{
v: 75,
u: 2,
n: 'burner max power',
c: 'burnmaxpower',
},
{
v: -6,
u: 1,
n: 'hysteresis on temperature',
c: 'boilhyston',
},
{
v: 6,
u: 1,
n: 'hysteresis off temperature',
c: 'boilhystoff',
},
{
v: 0,
u: 2,
n: 'burner current power',
c: '',
},
{
v: 303226,
u: 15,
n: '# burner starts',
c: '',
},
{
v: 510634,
u: 7,
n: 'total burner operating time',
c: '',
},
{
v: 415235,
u: 7,
n: 'total heat operating time',
c: '',
},
{
v: 4338730,
u: 7,
n: 'total UBA operating time',
c: '',
},
{
v: '1C(210) 06.06.2020 12:07',
u: 0,
n: 'last error code',
c: '',
},
{
v: '0H',
u: 0,
n: 'service code',
c: '',
},
{
v: 203,
u: 0,
n: 'service code number',
c: '',
},
{
v: '01.01.2012',
u: 0,
n: 'maintenance set date',
c: '',
},
{
v: 'off',
u: 0,
n: 'maintenance scheduled',
c: 'maintenance',
},
{
v: 6000,
u: 6,
n: 'maintenance set time',
c: '',
},
{
v: 60,
u: 1,
n: '(ww) selected temperature',
c: '',
},
{
v: 62,
u: 1,
n: '(ww) set temperature',
c: 'wwsettemp',
},
{
v: 'flow',
u: 0,
n: '(ww) type',
c: '',
},
{
v: 'hot',
u: 0,
n: '(ww) comfort',
c: 'wwcomfort',
},
{
v: 40,
u: 0,
n: '(ww) flow temperature offset',
c: 'wwflowtempoffset',
},
{
v: 100,
u: 2,
n: '(ww) max power',
c: 'wwmaxpower',
},
{
v: false,
u: 16,
n: '(ww) circulation pump available',
c: 'wwcircpump',
},
{
v: 'charge pump',
u: 0,
n: '(ww) charging type',
c: '',
},
{
v: 70,
u: 1,
n: '(ww) disinfection temperature',
c: 'wwdisinfectiontemp',
},
{
v: 'off',
u: 0,
n: '(ww) circulation pump frequency',
c: 'wwcircmode',
},
{
v: false,
u: 16,
n: '(ww) circulation active',
c: 'wwcirc',
},
{
v: 44.4,
u: 1,
n: '(ww) current intern temperature',
c: '',
},
{
v: 0,
u: 3,
n: '(ww) current tap water flow',
c: '',
},
{
v: 44.4,
u: 1,
n: '(ww) storage intern temperature',
c: '',
},
{
v: true,
u: 16,
n: '(ww) activated',
c: 'wwactivated',
},
{
v: false,
u: 16,
n: '(ww) one time charging',
c: 'wwonetime',
},
{
v: false,
u: 16,
n: '(ww) disinfecting',
c: '',
},
{
v: false,
u: 16,
n: '(ww) charging',
c: '',
},
{
v: false,
u: 16,
n: '(ww) recharging',
c: '',
},
{
v: true,
u: 16,
n: '(ww) temperature ok',
c: '',
},
{
v: false,
u: 16,
n: '(ww) active',
c: '',
},
{
v: true,
u: 16,
n: '(ww) heating',
c: '',
},
{
v: 268671,
u: 15,
n: '(ww) # starts',
c: '',
},
{
v: 95399,
u: 7,
n: '(ww) active time',
c: '',
},
],
}
const emsesp_devicedata_3 = {
name: 'Controller: BC1',
data: [],
}
// NETWORK
app.get(NETWORK_STATUS_ENDPOINT, (req, res) => {
res.json(network_status)
})
app.get(NETWORK_SETTINGS_ENDPOINT, (req, res) => {
res.json(network_settings)
})
app.post(NETWORK_SETTINGS_ENDPOINT, (req, res) => {
res.json(network_settings)
})
app.get(LIST_NETWORKS_ENDPOINT, (req, res) => {
res.json(list_networks)
})
app.get(SCAN_NETWORKS_ENDPOINT, (req, res) => {
res.sendStatus(202)
})
// AP
app.get(AP_SETTINGS_ENDPOINT, (req, res) => {
res.json(ap_settings)
})
app.get(AP_STATUS_ENDPOINT, (req, res) => {
res.json(ap_status)
})
app.post(AP_SETTINGS_ENDPOINT, (req, res) => {
res.json(ap_settings)
})
// OTA
app.get(OTA_SETTINGS_ENDPOINT, (req, res) => {
res.json(ota_settings)
})
app.post(OTA_SETTINGS_ENDPOINT, (req, res) => {
res.json(ota_settings)
})
// MQTT
app.get(MQTT_SETTINGS_ENDPOINT, (req, res) => {
res.json(mqtt_settings)
})
app.post(MQTT_SETTINGS_ENDPOINT, (req, res) => {
res.json(mqtt_settings)
})
app.get(MQTT_STATUS_ENDPOINT, (req, res) => {
res.json(mqtt_status)
})
// NTP
app.get(NTP_SETTINGS_ENDPOINT, (req, res) => {
res.json(ntp_settings)
})
app.post(NTP_SETTINGS_ENDPOINT, (req, res) => {
res.json(ntp_settings)
})
app.get(NTP_STATUS_ENDPOINT, (req, res) => {
res.json(ntp_status)
})
app.post(TIME_ENDPOINT, (req, res) => {
res.sendStatus(200)
})
// SYSTEM
app.get(SYSTEM_STATUS_ENDPOINT, (req, res) => {
res.json(system_status)
})
app.get(SECURITY_SETTINGS_ENDPOINT, (req, res) => {
res.json(security_settings)
})
app.post(SECURITY_SETTINGS_ENDPOINT, (req, res) => {
res.json(security_settings)
})
app.get(FEATURES_ENDPOINT, (req, res) => {
res.json(features)
})
app.get(VERIFY_AUTHORIZATION_ENDPOINT, (req, res) => {
res.json(verify_authentication)
})
app.post(RESTART_ENDPOINT, (req, res) => {
res.sendStatus(200)
})
app.post(FACTORY_RESET_ENDPOINT, (req, res) => {
res.sendStatus(200)
})
app.post(UPLOAD_FIRMWARE_ENDPOINT, (req, res) => {
res.sendStatus(200)
})
app.post(SIGN_IN_ENDPOINT, (req, res) => {
res.json(signin)
})
app.get(GENERATE_TOKEN_ENDPOINT, (req, res) => {
res.json(generate_token)
})
// EMS-ESP Project stuff
app.get(EMSESP_SETTINGS_ENDPOINT, (req, res) => {
res.json(emsesp_settings)
})
app.post(EMSESP_SETTINGS_ENDPOINT, (req, res) => {
res.json(emsesp_settings)
})
app.get(EMSESP_ALLDEVICES_ENDPOINT, (req, res) => {
res.json(emsesp_alldevices)
})
app.post(EMSESP_SCANDEVICES_ENDPOINT, (req, res) => {
res.sendStatus(200)
})
app.get(EMSESP_STATUS_ENDPOINT, (req, res) => {
res.json(emsesp_status)
})
app.post(EMSESP_DEVICEDATA_ENDPOINT, (req, res) => {
const id = req.body.id
if (id == 1) {
const encoded = msgpack.encode(emsesp_devicedata_1)
res.write(encoded, 'binary')
res.end(null, 'binary')
}
if (id == 2) {
const encoded = msgpack.encode(emsesp_devicedata_2)
res.write(encoded, 'binary')
res.end(null, 'binary')
}
if (id == 3) {
const encoded = msgpack.encode(emsesp_devicedata_3)
res.write(encoded, 'binary')
res.end(null, 'binary')
}
})
app.post(WRITE_VALUE_ENDPOINT, (req, res) => {
const devicevalue = req.body.devicevalue
const id = req.body.id
console.log(id)
console.log(devicevalue)
res.sendStatus(200)
})
app.post(EMSESP_BOARDPROFILE_ENDPOINT, (req, res) => {
const board_profile = req.body.code
const data = {
led_gpio: 1,
dallas_gpio: 2,
rx_gpio: 3,
tx_gpio: 4,
pbutton_gpio: 5,
}
if (board_profile == 'S32') {
// BBQKees Gateway S32
data.led_gpio = 2
data.dallas_gpio = 18
data.rx_gpio = 23
data.tx_gpio = 5
data.pbutton_gpio = 0
} else if (board_profile == 'E32') {
// BBQKees Gateway E32
data.led_gpio = 2
data.dallas_gpio = 4
data.rx_gpio = 5
data.tx_gpio = 17
data.pbutton_gpio = 33
} else if (board_profile == 'MH-ET') {
// MH-ET Live D1 Mini
data.led_gpio = 2
data.dallas_gpio = 18
data.rx_gpio = 23
data.tx_gpio = 5
data.pbutton_gpio = 0
} else if (board_profile == 'NODEMCU') {
// NodeMCU 32S
data.led_gpio = 2
data.dallas_gpio = 18
data.rx_gpio = 23
data.tx_gpio = 5
data.pbutton_gpio = 0
} else if (board_profile == 'LOLIN') {
// Lolin D32
data.led_gpio = 2
data.dallas_gpio = 18
data.rx_gpio = 17
data.tx_gpio = 16
data.pbutton_gpio = 0
} else if (board_profile == 'OLIMEX') {
// Olimex ESP32-EVB (uses U1TXD/U1RXD/BUTTON, no LED or Dallas)
data.led_gpio = 0
data.dallas_gpio = 0
data.rx_gpio = 36
data.tx_gpio = 4
data.pbutton_gpio = 34
// data = { 0, 0, 36, 4, 34};
} else if (board_profile == 'TLK110') {
// Generic Ethernet (TLK110)
data.led_gpio = 2
data.dallas_gpio = 4
data.rx_gpio = 5
data.tx_gpio = 17
data.pbutton_gpio = 33
} else if (board_profile == 'LAN8720') {
// Generic Ethernet (LAN8720)
data.led_gpio = 2
data.dallas_gpio = 4
data.rx_gpio = 5
data.tx_gpio = 17
data.pbutton_gpio = 33
}
res.json(data)
})
// create helper middleware so we can reuse server-sent events
const useServerSentEventsMiddleware = (req, res, next) => {
res.setHeader('Content-Type', 'text/event-stream')
res.setHeader('Cache-Control', 'no-cache')
// only if you want anyone to access this endpoint
res.setHeader('Access-Control-Allow-Origin', '*')
res.flushHeaders()
const sendEventStreamData = (data) => {
const sseFormattedResponse = `data: ${JSON.stringify(data)}\n\n`
res.write(sseFormattedResponse)
}
// we are attaching sendEventStreamData to res, so we can use it later
Object.assign(res, {
sendEventStreamData,
})
next()
}
const streamLog = (req, res) => {
let interval = setInterval(function generateAndSendLog() {
count = count + 1
const data = {
time: '000+00:00:00.000',
level: 4,
message: 'this is message #' + count,
}
res.sendEventStreamData(data)
}, 1000)
res.on('close', () => {
clearInterval(interval)
res.end()
})
}
// event source, server-sent events SSE
const ES_LOG_ENDPOINT = ES_ENDPOINT_ROOT + 'log'
let count = 0
server.get(ES_LOG_ENDPOINT, useServerSentEventsMiddleware, streamLog)
server.listen(es_port, () =>
console.log(
`Mock EventSource server for EMS-ESP listening at http://localhost:${es_port}`,
),
)
// rest API
app.listen(port)
console.log(
`Mock RESTful API server for EMS-ESP is up and running at http://localhost:${port}`,
)