-
Notifications
You must be signed in to change notification settings - Fork 1
Binary Protocol
The binary protocol is used by connecting to TCP port 6001 on uscv2.naviensmartcontrol.com.
- Initial Connection Request
- State Request
- Device Control Request
- Trend Sample Request
- Trend Monthly Request
- Trend Yearly Request
- Channel Information Response
- State Response
- Device Control Response
- Trend Sample Response
- Trend Monthly Response
- Trend Yearly Response
Upon initial connection, a request containing the authenticated username
Example
00000000 75 73 65 72 6e 61 6d 65 24 69 50 68 6f 6e 65 31 username$iPhone1
00000010 2e 30 24 31 32 33 34 35 36 37 38 39 31 32 33 34 .0$1234567891234
00000020 35 36 37 567
Upon successfully submission of the Initial Connection Request, the binary protocol will respond with a Channel Information Response such as the following
00000000 XX XX XX XX XX XX XX XX 01 01 0e 00 04 01 00 00
00000010 01 00 00 00 00 00 01 00 00 02 02 00 00 01 00 00
00000020 00 00 00 01 00 00 02 03 01 01 02 62 b6 20 20 03
00000030 01 00 00 01
Of this, the first 12 bytes are the Common Response Header consisting of the following
Description: An 8 byte unique ID used in all requests and responses. The first 6 bytes are the NaviLink's MAC address
Example: 01 02 03 04 05 06 07 08
(Denoted as XX XX XX XX XX XX XX XX in the sample capture above)
Description: A one byte country code designation
Example: 01
Description: A one byte ID identifying the message type (as specified in the ControlType enum)
Example: 01
corresponding with the ControlType.CHANNEL_INFOMATION enum
Description: A one byte value of the software version major number
Example: 0e
= 14 dec
Description: A one byte value of the software version minor number
Example: 00
= 0 dec
The rest of the Channel Information Response starts at array position 12 (byte 13)
channelUse = 04 matched to enum CHANNEL_3_USE and set to ChannelUse.CHANNEL_3_USE (NPE device is connected to NaviLink serial port 3)
computed firmware version = swVersionMajor * 100 + swVersionMinor = 1400 dec since this is < 1500, b1 = 13 (otherwise b1 = 15)
loops 3 times (index 0-2), one loop per channel (13 bytes per channel)
01 00 00 01 00 00 00 00 00 01 00 00 02
-channel.channel = 01
-channel.deviceSorting = 00 matched to enum NO_DEVICE and set to DeviceSorting.NO_DEVICE
-channel.deviceCount = 00
-channel.deviceTempFlag = 01 matched to enum CELSIUS and set to TemperatureType.CELSIUS
-channel.mininumSettingWaterTemperature = 00 & 0xFF = 0
-channel.maxinumSettingWaterTemperature = 00 & 0xFF = 0
-channel.heatingMininumSettingWaterTemperature = 00 & 0xFF = 0
-channel.heatingMaxinumSettingWaterTemperature = 00 & 0xFF = 0
-channel.useOnDemand = 00 matched to enum UNKNOWN and set to OnDemandFlag.UNKNOWN
-channel.heatingControl = 01 matched to enum SUPPLY and set to HeatingControl.SUPPLY
-channel.wwsdFlag = 00 wwsdFlag is a bitfield. For bits in byte: 76543210 -> 0 is boolean matched to enum OK and set to WWSDFlag.OK
-channel.commercialLock derived from wwsdFlag bitfield value (For bits in byte: 76543210 -> 1 is commercialLock), 0 matched to enum OK and set to CommercialLockFlag.OK
-channel.hotwaterPossibility derived from wwsdFlag bitfield value (For bits in byte: 76543210 -> 2 is hotwaterPossibility), 0 matched to enum OFF and set to NFBWaterFlag.OFF
-channel.recirculationPossibility derived from wwsdFlag bitfield value (For bits in byte: 76543210 -> 3 is recirculationPossibility), matched to enum OFF and set to RecirculationFlag.OFF
-channel.useWarmWater = 02 matched to enum OFF and set to OnOFFFlag.OFF
-would also read two more bytes for channel.mininumSettingRecirculationTemperature and channel.maxinumSettingRecirculationTemperature if the computed firmware version is >1500, but the app does not properly evaluate this condition (bug)
02 00 00 01 00 00 00 00 00 01 00 00 02
03 01 01 02 62 b6 20 20 03 01 00 00 01
-channel.channel = 03
-channel.deviceSorting = 01 matched to enum NPE and set to DeviceSorting.NPE
-channel.deviceCount = 01
-channel.deviceTempFlag = 02 matched to enum FAHRENHEIT and set to TemperatureType.FAHRENHEIT
-channel.mininumSettingWaterTemperature = 62 & 0xFF = 98 dec
-channel.maxinumSettingWaterTemperature = b6 & 0xFF = 182 dec
-channel.heatingMininumSettingWaterTemperature = 20 & 0xFF = 32 dec (probably a default value as this feature is not in use)
-channel.heatingMaxinumSettingWaterTemperature = 20 & 0xFF = 32 dec (probably a default value as this feature is not in use)
-channel.useOnDemand = 03 matched to enum WARMUP and set to OnDemandFlag.WARMUP
-channel.heatingControl = 01 matched to enum SUPPLY and set to HeatingControl.SUPPLY
-channel.wwsdFlag = 00 wwsdFlag is a bitfield. For bits in byte: 76543210 -> 0 is boolean matched to enum OK and set to WWSDFlag.OK
-channel.commercialLock derived from wwsdFlag bitfield value (For bits in byte: 76543210 -> 1 is commercialLock), 0 matched to enum OK and set to CommercialLockFlag.OK
-channel.hotwaterPossibility derived from wwsdFlag bitfield value (For bits in byte: 76543210 -> 2 is hotwaterPossibility), 0 matched to enum OFF and set to NFBWaterFlag.OFF
-channel.recirculationPossibility derived from wwsdFlag bitfield value (For bits in byte: 76543210 -> 3 is recirculationPossibility), matched to enum OFF and set to RecirculationFlag.OFF
-channel.highTemperature = 00 matched to enum TEMPERATURE_60 and set to HighTemperature.TEMPERATURE_60
-channel.useWarmWater = 01 matched to enum ON OnOFFFlag.ON
-would also read two more bytes for channel.mininumSettingRecirculationTemperature and channel.maxinumSettingRecirculationTemperature if the computed firmware version is >1500, but the app does not properly evaluate this condition (bug)
00000000 07 99 00 a6 37 00 XX XX XX XX XX XX XX XX 01 03
00000010 01 01 02 00 00 00 00 00 00 00 00 00 00 00 00 00
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000030 00 00 00 00 00
All requests share a hardcoded 6 byte prefix that contains the following:
07 99 00 a6 37 00
-stx = 07
-did = 99
-reserve = 00
-cmd = a6
-dataLength = 37
-dSid = 00
device ID = XX XX XX XX XX XX XX XX
Rest of status request follows starting at array position 14 (byte 15):
commandCount = 01
currentControlChannel = 03 (NPE device is connected to Navilink serial port 3)
deviceNumber = 01 (first device on the serial bus)
controlSorting = 01 (1 for deviceInfo requests, and 2 for deviceControlWeekly and deviceControl)
infoItem = 02 matched to enum STATE and set to ControlType.STATE (This field is only used when info is requested as per this request)
controlItem = 00 matched to enum UNKNOWN and set to ControlType.UNKNOWN (This field is only used when controlling)
controlValue = 00 (this is set to 0 for info requests, 1 for setting weekly schedule info or another value when controlling)
controlValue_WeeklyDay = 00
controlValue_WeeklyCount = 00
controlValue_WeeklyDay_1_Hour = 00
controlValue_WeeklyDay_1_Minute = 00
controlValue_WeeklyDay_1_Flag = 00
controlValue_WeeklyDay_2_Hour = 00
controlValue_WeeklyDay_2_Minute = 00
controlValue_WeeklyDay_2_Flag = 00
controlValue_WeeklyDay_3_Hour = 00
controlValue_WeeklyDay_3_Minute = 00
controlValue_WeeklyDay_3_Flag = 00
controlValue_WeeklyDay_4_Hour = 00
controlValue_WeeklyDay_4_Minute = 00
controlValue_WeeklyDay_4_Flag = 00
controlValue_WeeklyDay_5_Hour = 00
controlValue_WeeklyDay_5_Minute = 00
controlValue_WeeklyDay_5_Flag = 00
controlValue_WeeklyDay_6_Hour = 00
controlValue_WeeklyDay_6_Minute = 00
controlValue_WeeklyDay_6_Flag = 00
controlValue_WeeklyDay_7_Hour = 00
controlValue_WeeklyDay_7_Minute = 00
controlValue_WeeklyDay_7_Flag = 00
controlValue_WeeklyDay_8_Hour = 00
controlValue_WeeklyDay_8_Minute = 00
controlValue_WeeklyDay_8_Flag = 00
controlValue_WeeklyDay_9_Hour = 00
controlValue_WeeklyDay_9_Minute = 00
controlValue_WeeklyDay_9_Flag = 00
controlValue_WeeklyDay_10_Hour = 00
controlValue_WeeklyDay_10_Minute = 00
controlValue_WeeklyDay_10_Flag = 00
00000000 XX XX XX XX XX XX XX XX 01 02 0e 00 13 05 1c 00
00000010 01 01 03 01 00 00 01 2f b3 22 c7 40 00 00 7d 7b
00000020 2b 00 3b 00 20 20 01 02 02 02 00 01 00 00 00 00
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000040 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000060 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 00
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000080 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000A0 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00
000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000C0 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 00
000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000E0 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 00
000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000100 00 00 00 00 00 00 00 00 00 00 00 20 20 20 20
Common response header:
deviceID = XX XX XX XX XX XX XX XX
countryCD = 01
controlType = 02 matched to enum STATE and set to ControlType.STATE
swVersionMajor = 0e & 0xFF = 14 dec
swVersionMinor = 00 & 0xFF = 0
Status response details start at array position 12 (byte 13):
controllerVersion = 13 05
pannelVersion = 1c 00
deviceSorting = 01 matched to enum NPE and set to DeviceSorting.NPE
deviceCount = 01 Corresponds with the number of devices on serial bus (if more than 1 => cascaded devices)
currentChannel = 03 (device is connected to serial port 3 on the Navilink)
deviceNumber = 01 Corresponds with this device's address on the serial bus
errorCD = (00 & 0xFF) + (00 & 0xFF) * 256 = 0
operationDeviceNumber = 01 This changes to 0 when the unit is not actively running. This is also used to compute stats for cascaded devices
AverageCalorimeter = 2f & 0xFF = 2F (47 dec, this is converted in the app by 47 / 2 = 23.5 %)
gasInstantUse = (b3 & 0xFF) + (22 & 0xFF) * 256 = 0xB3 + (0x22 * 256) = 179 + 8704 = 8883 (This is converted from kilocalories in the app by 8883 * 3.968 = 35,247.744 and rounded to 35,247.7 BTU. If converted accurately, should actually be 35,227.02 BTU)
gasAccumulatedUse = c7 40 00 00 treat as little endian and convert to int = 16583 (This is converted from m^3/10 in the app by 16583 * 35.314667 / 10.0 = 58,562.3122861 and rounded to 58562.3 ft^3)
hotWaterSettingTemperature = 7d & 0xFF = 125 (F)
hotWaterCurrentTemperature = 7b & 0xFF = 123 (F)
hotWaterFlowRate = (2b & 0xFF) + (00 & 0xFF) * 256 = 43 + 0 = 43 (This is converted from LPM/10 in the app by 43 / 3.785 / 10.0 = 1.1360 and rounded to 1.1 GPM. If converted accurately is 1.13594 GPM, but with rounding it wouldn't matter)
hotWaterTemperature = 3b & 0xFF = 59 (F, this is actually the inlet temperature per the app)
heatSettingTemperature = 00 & 0xFF = 0
currentWorkingFluidTemperature = 20 & 0xFF = 32 dec (probably a default value when not using external recirc)
currentReturnWaterTemperature = 20 & 0xFF = 32 dec (probably a default value when not using external recirc)
powerStatus = 01 matched to enum ON and set to OnOFFFlag.ON
heatStatus = 02 matched to enum OFF and set to OnOFFFlag.OFF
useOnDemand = 02 matched to enum OFF and set to OnOFFFlag.OFF
weeklyControl = 02 matched to enum OFF and set to OnOFFFlag.OFF
totalDaySequence = 00
Loops 7 times (0-6), one for each day of week contained in the status response
-matches day.daySequence to enums defined in KDWeekly.DayOfWeek based on values 01-07 in binary data
-for array position 43 (byte 44) = 01:
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
--weeklyTotalCount = 00 (loops again from 0 to day.weeklyTotalCount max of 10 on/off times per day of week)
---reads 3 byte sets of hour, minute and OnOFFFlag enum
00 00 00
00 00 00
00 00 00
00 00 00
00 00 00
00 00 00
00 00 00
00 00 00
00 00 00
00 00 00
hotWaterAverageTemperature = 20 & 0xFF = 32 dec (probably a default value when not using external recirc)
inletAverageTemperature = 20 & 0xFF = 32 dec (probably a default value when not using external recirc)
supplyAverageTemperature = 20 & 0xFF = 32 dec (probably a default value when not using external recirc)
returnAverageTemperature = 20 & 0xFF = 32 dec (probably a default value when not using external recirc)
Would read an additional two bytes for recirculationSettingTemperature and recirculationCurrentTemperature if recirculation was enabled (the status response would be two bytes larger)
00000000 07 99 00 a6 37 00 XX XX XX XX XX XX XX XX 01 03
00000010 01 02 00 01 02 00 00 00 00 00 00 00 00 00 00 00
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000030 00 00 00 00 00
Rest of status request follows starting at array position 14 (byte 15):
commandCount = 01
currentControlChannel = 03 (NPE device is connected to Navilink serial port 3)
deviceNumber = 01 (first device on the serial bus)
controlSorting = 02 (1 for deviceInfo requests, and 2 for deviceControlWeekly and deviceControl)
infoItem = 00 (this field is set to 0 when controlling)
controlItem = 01 matched to enum POWER
controlValue = 02 This corresponds with enum OnOFFFlag.OFF
00000000 07 99 00 a6 37 00 XX XX XX XX XX XX XX XX 01 03
00000010 01 02 00 01 01 00 00 00 00 00 00 00 00 00 00 00
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000030 00 00 00 00 00
Rest of status request follows starting at array position 14 (byte 15):
commandCount = 01
currentControlChannel = 03 (NPE device is connected to Navilink serial port 3)
deviceNumber = 01 (first device on the serial bus)
controlSorting = 02 (1 for deviceInfo requests, and 2 for deviceControlWeekly and deviceControl)
infoItem = 00 (this field is set to 0 when controlling)
controlItem = 01 matched to enum POWER
controlValue = 01 This corresponds with enum OnOFFFlag.ON
00000000 07 99 00 a6 37 00 XX XX XX XX XX XX XX XX 01 03
00000010 01 02 00 03 78 00 00 00 00 00 00 00 00 00 00 00
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000030 00 00 00 00 00
Rest of status request follows starting at array position 14 (byte 15):
commandCount = 01
currentControlChannel = 03 (NPE device is connected to Navilink serial port 3)
deviceNumber = 01 (first device on the serial bus)
controlSorting = 02 (deviceControl)
infoItem = 00 (this field is set to 0 when controlling)
controlItem = 03 matched to enum WATER_TEMPERATURE
controlValue = 78 (120 dec)
00000000 07 99 00 a6 37 00 XX XX XX XX XX XX XX XX 01 03
00000010 01 02 00 06 01 01 02 01 0a 02 02 00 02 00 00 00
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000030 00 00 00 00 00
Rest of status request follows starting at array position 14 (byte 15):
commandCount = 01
currentControlChannel = 03 (NPE device is connected to Navilink serial port 3)
deviceNumber = 01 (first device on the serial bus)
controlSorting = 02 (deviceControl)
infoItem = 00 (this field is set to 0 when controlling)
controlItem = 06 matched to enum DeviceControl.WEEKLY
controlValue = 01 matched to enum OnOFFFlag.ON
controlValue_WeeklyDay = 01 corresponds with enum DayOfWeek.SUN
controlValue_WeeklyCount = 02 (total of 2 entries)
controlValue_WeeklyDay_1_Hour = 01 (1AM 24H time)
controlValue_WeeklyDay_1_Minute = 0a (10 dec => 01:10)
controlValue_WeeklyDay_1_Flag = 02 corresponds with enum OnOFFFlag.OFF
controlValue_WeeklyDay_2_Hour = 02 (2AM 24H time)
controlValue_WeeklyDay_2_Minute = 00 (0 dec => 02:00)
controlValue_WeeklyDay_2_Flag = 02 corresponds with enum OnOFFFlag.OFF
controlValue_WeeklyDay_3_Hour = 00
controlValue_WeeklyDay_3_Minute = 00
controlValue_WeeklyDay_3_Flag = 00
controlValue_WeeklyDay_4_Hour = 00
controlValue_WeeklyDay_4_Minute = 00
controlValue_WeeklyDay_4_Flag = 00
controlValue_WeeklyDay_5_Hour = 00
controlValue_WeeklyDay_5_Minute = 00
controlValue_WeeklyDay_5_Flag = 00
controlValue_WeeklyDay_6_Hour = 00
controlValue_WeeklyDay_6_Minute = 00
controlValue_WeeklyDay_6_Flag = 00
controlValue_WeeklyDay_7_Hour = 00
controlValue_WeeklyDay_7_Minute = 00
controlValue_WeeklyDay_7_Flag = 00
controlValue_WeeklyDay_8_Hour = 00
controlValue_WeeklyDay_8_Minute = 00
controlValue_WeeklyDay_8_Flag = 00
controlValue_WeeklyDay_9_Hour = 00
controlValue_WeeklyDay_9_Minute = 00
controlValue_WeeklyDay_9_Flag = 00
controlValue_WeeklyDay_10_Hour = 00
controlValue_WeeklyDay_10_Minute = 00
controlValue_WeeklyDay_10_Flag = 00
Upon receiving a properly formed Device Control Request, the protocol will respond with a State Response showing the updated state.
00000000 07 99 00 a6 37 00 XX XX XX XX XX XX XX XX 01 03
00000010 01 01 03 00 00 00 00 00 00 00 00 00 00 00 00 00
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000030 00 00 00 00 00
Rest of status request follows starting at array position 14 (byte 15):
commandCount = 01
currentControlChannel = 03 (NPE device is connected to Navilink serial port 3)
deviceNumber = 01 (first device on the serial bus)
controlSorting = 01 (deviceInfo)
infoItem = 03 matched to ControlType.TREND_SAMPLE
controlItem = 00
controlValue = 00
00000000 XX XX XX XX XX XX XX XX 01 03 0e 00 13 05 1c 00
00000010 01 01 03 01 00 00 00 e8 05 00 00 f7 40 00 00 3b
00000020 3a 42 00 00 00 00 00
Common response header:
deviceID = XX XX XX XX XX XX XX XX
countryCD = 01
controlType = 03 matched to enum ControlType.TREND_SAMPLE
swVersionMajor = 0e & 0xFF = 14 dec
swVersionMinor = 00 & 0xFF = 0
The app does not use the following (status-like) response details starting at array position 12 (byte 13):
controllerVersion = 13 05
pannelVersion = 1c 00
deviceSorting = 01 matched to enum NPE and set to DeviceSorting.NPE
deviceCount = 01
currentChannel = 03 (device is connected to serial port 3 on the Navilink)
deviceNumber = 01
Trend sample information response starts at array position 20 (byte 21):
modelInfo = 00 00 00
totalOperatedTime = e8 05 00 00 treat as little endian and convert to int = 1512 (hour)
totalGasAccumulateSum = f7 40 00 00 treat as little endian and convert to int = 16631 (this is not displayed, but likely corresponds with gasAccumulatedUse used in the state response and would be converted from m^3/10 in the app by 16631 * 35.314667 / 10.0 = 58,731.8226877 and rounded to 58,731.8 ft^3)
totalHotWaterAccumulateSum = 3b 3a 42 00 treat as little endian and convert to int (this is not displayed)
totalCHOperatedTime = 00 00 00 00 (heating is not used)
if the response payload was >39, would read another four bytes for totalDHWUsageTime
00000000 07 99 00 a6 37 00 XX XX XX XX XX XX XX XX 01 03
00000010 01 01 04 00 00 00 00 00 00 00 00 00 00 00 00 00
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000030 00 00 00 00 00
Rest of status request follows starting at array position 14 (byte 15):
commandCount = 01
currentControlChannel = 03 (NPE device is connected to Navilink serial port 3)
deviceNumber = 01 (first device on the serial bus)
controlSorting = 01 (deviceInfo)
infoItem = 04 matched to ControlType.TREND_MONTH
controlItem = 00
controlValue = 00
00000000 XX XX XX XX XX XX XX XX 01 04 0e 00 13 05 1c 00
00000010 01 01 03 01 1f 01 00 00 00 00 00 00 00 00 00 00
00000020 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000040 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000050 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000080 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00
00000090 00 00 00 00 00 00 00 00 00 07 00 00 00 00 00 00
000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08
000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000C0 00 00 00 00 00 09 00 00 00 00 00 00 00 00 00 00
000000D0 00 00 00 00 00 00 00 00 00 00 00 0a 00 00 00 00
000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000F0 00 0b 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000100 00 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 00
00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 0d 00 00
00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000130 00 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 00
00000140 00 00 00 00 00 00 00 00 00 0f 00 00 00 01 00 00
00000150 00 00 00 00 00 02 00 00 00 00 00 20 20 00 00 10
00000160 00 00 00 09 00 00 00 00 00 00 00 06 00 00 00 00
00000170 00 20 20 00 00 11 00 00 00 05 00 00 00 6c 09 00
00000180 00 04 00 00 00 00 00 20 20 01 00 12 00 00 00 08
00000190 00 00 00 00 00 00 00 05 00 00 00 00 00 20 20 00
000001A0 00 13 00 00 00 17 00 00 00 69 12 00 00 09 00 00
000001B0 00 00 00 20 20 02 00 14 00 00 00 0b 00 00 00 27
000001C0 09 00 00 0c 00 00 00 00 00 20 20 01 00 15 00 00
000001D0 00 04 00 00 00 d4 08 00 00 04 00 00 00 00 00 20
000001E0 20 01 00 16 00 00 00 00 00 00 00 00 00 00 00 00
000001F0 00 00 00 00 00 00 00 00 00 17 00 00 00 00 00 00
00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18
00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000220 00 00 00 00 00 19 00 00 00 00 00 00 00 00 00 00
00000230 00 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 00
00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000250 00 1b 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000260 00 00 00 00 00 00 00 1c 00 00 00 00 00 00 00 00
00000270 00 00 00 00 00 00 00 00 00 00 00 00 00 1d 00 00
00000280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000290 00 00 00 1e 00 00 00 00 00 00 00 00 00 00 00 00
000002A0 00 00 00 00 00 00 00 00 00 1f 00 00 00 00 00 00
000002B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Common response header:
deviceID = XX XX XX XX XX XX XX XX
countryCD = 01
controlType = 04 matched to enum ControlType.TREND_MONTH
swVersionMajor = 0e & 0xFF = 14 dec
swVersionMinor = 00 & 0xFF = 0
The app does not use the following (status-like) response details starting at array position 12 (byte 13):
controllerVersion = 13 05
pannelVersion = 1c 00
deviceSorting = 01 matched to enum NPE and set to DeviceSorting.NPE
deviceCount = 01
currentChannel = 03 (device is connected to serial port 3 on the Navilink)
deviceNumber = 01
Trend month information response starts at array position 20 (byte 21):
totalDaySequence = 1f = 31 dec
Loops 31 times and reads the following
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-trendData.sequence = 01
-trendData.modelInfo = 00 00 00
-trendData.gasAccumulatedUse = 00 00 00 00 treat as little endian and convert to int = 0 converted from m^3/10 in the app by 0 * 35.314667 / 10.0 = 0 and rounded to 0 ft^3
-trendData.hotWaterAccumulatedUse = 00 00 00 00 treat as little endian and convert to int = 0 (not shown in the app for NPE, but for others that do this is converted in the app by 0 / 3.785 / 10.0 = 0 and rounded to 0 G)
-trendData.hotWaterOperatedCount = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 0 dec
-trendData.onDemandUseCount = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 0 dec
-trendData.heatAccumulatedUse = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 0 dec
-trendData.outdoorAirMaxTemperature = 00
-trendData.outdoorAirMinTemperature = 00
-trendData.dHWAccumulatedUse = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 0 dec
...
14 00 00 00 0b 00 00 00 27 09 00 00 0c 00 00 00 00 00 20 20 01 00
-trendData.sequence = 14
-trendData.modelInfo = 00 00 00
-trendData.gasAccumulatedUse = 0b 00 00 00 treat as little endian and convert to int = 11 converted from m^3/10 in the app by 11 * 35.314667 / 10.0 = 38.8461337 and rounded to 38.9 ft^3
-trendData.hotWaterAccumulatedUse = 27 09 00 00 treat as little endian and convert to int = 2343 (not shown in the app for NPE, but for others that do this is converted in the app by 2343 / 3.785 / 10.0 = 61.902246 and rounded to 61.9 G)
-trendData.hotWaterOperatedCount = 0c 00 => ((0c & 0xFF) + (00 & 0xFF) * 256 = 12 dec converted in the app by 12 * 10 = 120
-trendData.onDemandUseCount = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 0 dec
-trendData.heatAccumulatedUse = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 00 dec
-trendData.outdoorAirMaxTemperature = 20 = 32 dec (probably a default value as this feature is not in use)
-trendData.outdoorAirMinTemperature = 20 = 32 dec (probably a default value as this feature is not in use)
-trendData.dHWAccumulatedUse = 01 00 => ((01 & 0xFF) + (00 & 0xFF) * 256 = 1 dec
00000000 07 99 00 a6 37 00 XX XX XX XX XX XX XX XX 01 03
00000010 01 01 05 00 00 00 00 00 00 00 00 00 00 00 00 00
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000030 00 00 00 00 00
Rest of status request follows starting at array position 14 (byte 15):
commandCount = 01
currentControlChannel = 03 (NPE device is connected to Navilink serial port 3)
deviceNumber = 01 (first device on the serial bus)
controlSorting = 01 (deviceInfo)
infoItem = 05 matched to ControlType.TREND_YEAR
controlItem = 00
controlValue = 00
00000000 XX XX XX XX XX XX XX XX 01 05 0e 00 13 05 1c 00
00000010 01 01 03 01 18 01 00 00 00 00 00 00 00 00 00 00
00000020 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000040 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000050 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000080 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00
00000090 00 00 00 00 00 00 00 00 00 07 00 00 00 00 00 00
000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08
000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000C0 00 00 00 00 00 09 00 00 00 00 00 00 00 00 00 00
000000D0 00 00 00 00 00 00 00 00 00 00 00 0a 00 00 00 00
000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000F0 00 0b 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000100 00 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 00
00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 0d 00 00
00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000130 00 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 00
00000140 00 00 00 00 00 00 00 00 00 0f 00 00 00 00 00 00
00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000170 00 00 00 00 00 11 00 00 00 00 00 00 00 00 00 00
00000180 00 00 00 00 00 00 00 00 00 00 00 12 00 00 00 00
00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001A0 00 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001B0 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 00
000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 15 00 00
000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001E0 00 00 00 16 00 00 00 00 00 00 00 00 00 00 00 00
000001F0 00 00 00 00 00 00 00 00 00 17 00 00 00 00 00 00
00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18
00000210 00 00 00 45 00 00 00 d0 2d 00 00 2f 00 00 00 00
00000220 00 20 20 05 00
Common response header:
deviceID = XX XX XX XX XX XX XX XX
countryCD = 01
controlType = 05 matched to enum ControlType.TREND_YEAR
swVersionMajor = 0e & 0xFF = 14 dec
swVersionMinor = 00 & 0xFF = 0
The app does not use the following (status-like) response details starting at array position 12 (byte 13):
controllerVersion = 13 05
pannelVersion = 1c 00
deviceSorting = 01 matched to enum NPE and set to DeviceSorting.NPE
deviceCount = 01
currentChannel = 03 (device is connected to serial port 3 on the Navilink)
deviceNumber = 01
Trend year information response starts at array position 20 (byte 21):
totalDaySequence = 18 = 24 dec (rolling month by month over two years. Last sequence is most recent)
Loops 24 times and reads 22 bytes
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-trendData.sequence = 01 (1 dec)
-trendData.modelInfo = 00 00 00
-trendData.gasAccumulatedUse = 00 00 00 00 treat as little endian and convert to int = 0 converted from m^3/10 in the app by 0 * 35.314667 / 10.0 = 0 and rounded to 0 ft^3
-trendData.hotWaterAccumulatedUse = 00 00 00 00 treat as little endian and convert to int = 0 (not shown in the app for NPE, but for others that do this is converted in the app by 0 / 3.785 / 10.0 = 0 and rounded to 0 G)
-trendData.hotWaterOperatedCount = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 0 dec
-trendData.onDemandUseCount = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 0 dec
-trendData.heatAccumulatedUse = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 0 dec
-trendData.outdoorAirMaxTemperature = 00 & 0xFF
-trendData.outdoorAirMinTemperature = 00 & 0xFF
-trendData.dHWAccumulatedUse = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 0 dec
...
18 00 00 00 45 00 00 00 d0 2d 00 00 2f 00 00 00 00 00 20 20 05 00
-trendData.sequence = 18 (24 dec)
-trendData.modelInfo = 00 00 00
-trendData.gasAccumulatedUse = 45 00 00 00 treat as little endian and convert to int = 69 converted from m^3/10 in the app by 69 * 35.314667 / 10.0 = 243.6712023 and rounded to 243.7 ft^3
-trendData.hotWaterAccumulatedUse = d0 2d 00 00 treat as little endian and convert to int = 11728 (not shown in the app for NPE, but for others that do this is converted in the app by 11728 / 3.785 / 10.0 = 309.854689 and rounded to 309.9 G)
-trendData.hotWaterOperatedCount = 2f 00 => ((2f & 0xFF) + (00 & 0xFF) * 256 = 47 dec converted in the app by 47 * 10 = 470
-trendData.onDemandUseCount = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 0 dec
-trendData.heatAccumulatedUse = 00 00 => ((00 & 0xFF) + (00 & 0xFF) * 256 = 0 dec
-trendData.outdoorAirMaxTemperature = 20 & 0xFF = 32 dec (probably a default value as this feature is not in use)
-trendData.outdoorAirMinTemperature = 20 & 0xFF = 32 dec (probably a default value as this feature is not in use)
-trendData.dHWAccumulatedUse = 05 00 => ((05 & 0xFF) + (00 & 0xFF) * 256 = 5 dec (hours)