actual key <\/em>is contained within the value as a delimited string. It\u2019s more data to send and more data to parse this way. So, again, maybe it\u2019s based on some DB or model system I\u2019m not familiar with. (Anyone recognize it?)<\/p>\nI\u2019ve substituted the actual values (as they are serial numbers of my devices) with text representations of what the value represented below:<\/p>\n
{\"keys\"<\/span>:\n [{\"key\"<\/span>:\"user.#USERID#\"<\/span>,\n \"version\"<\/span>:209478897,\"timestamp\"<\/span>:1324159145000},\n {\"key\"<\/span>:\"user_alert_dialog.#USERID#\"<\/span>,\n \"version\"<\/span>:-1320296685,\"timestamp\"<\/span>:1325967612000},\n {\"key\"<\/span>:\"structure.#STRUCTURE-GUID#\"<\/span>,\n \"version\"<\/span>:656192675,\"timestamp\"<\/span>:1325967612000},\n {\"key\"<\/span>:\"device.#DEVICE 1 SERIAL NUMBER#\"<\/span>,\n \"version\"<\/span>:1485027516,\"timestamp\"<\/span>:1326034984000},\n {\"key\"<\/span>:\"shared.#DEVICE 1 SERIAL NUMBER#\"<\/span>,\n \"version\"<\/span>:588844038,\"timestamp\"<\/span>:1326034818000},\n {\"key\"<\/span>:\"schedule.#DEVICE 1 SERIAL NUMBER#\"<\/span>,\n \"version\"<\/span>:1187107985,\"timestamp\"<\/span>:1326005677000},\n {\"key\"<\/span>:\"track.#DEVICE 1 SERIAL NUMBER#\"<\/span>,\n \"timestamp\"<\/span>:1326035650601,\"version\"<\/span>:1041047847},\n {\"key\"<\/span>:\"device.#DEVICE 2 SERIAL NUMBER#\"<\/span>,\n \"version\"<\/span>:149169270,\"timestamp\"<\/span>:1326034820000},\n {\"key\"<\/span>:\"shared.#DEVICE 2 SERIAL NUMBER#\"<\/span>,\n \"version\"<\/span>:659841570,\"timestamp\"<\/span>:1326034820000},\n {\"key\"<\/span>:\"schedule.#DEVICE 2 SERIAL NUMBER#\"<\/span>,\n \"version\"<\/span>:-2016290692,\"timestamp\"<\/span>:1326005625000},\n {\"key\"<\/span>:\"track.#DEVICE 2 SERIAL NUMBER#\"<\/span>,\n \"timestamp\"<\/span>:1326035650862,\"version\"<\/span>:528978433},\n {\"key\"<\/span>:\"device.#DEVICE 3 SERIAL NUMBER#\"<\/span>,\n \"version\"<\/span>:1637112547,\"timestamp\"<\/span>:1326035399000},\n {\"key\"<\/span>:\"shared.#DEVICE 3 SERIAL NUMBER#\"<\/span>,\n \"version\"<\/span>:760504326,\"timestamp\"<\/span>:1326035397000},\n {\"key\"<\/span>:\"schedule.#DEVICE 3 SERIAL NUMBER#\"<\/span>,\n \"version\"<\/span>:-314552357,\"timestamp\"<\/span>:1326003402000},\n {\"key\"<\/span>:\"track.#DEVICE 3 SERIAL NUMBER#\"<\/span>,\n \"version\"<\/span>:-645931164,\"timestamp\"<\/span>:1326035531802}]}\"<\/pre>\nWe\u2019ve got three thermostats, so there are always three sets of subscription requests for each call to subscribe.<\/strong><\/p>\nUsing my iPad, I adjusted the set point for our second story (#DEVICE 2#) down one degree Fahrenheit (to 67\u00b0).<\/p>\n
Within approximately a second, the most recent pending subscribe<\/strong> request returned with a far more interesting payload:<\/p>\njQuery17108417355176061392_1326035646750(\n { \"status\"<\/span>: 200,\n \"headers\"<\/span>: {\n \"X-nl-skv-key\"<\/span>: \"shared.#DEVICE 2 SERIAL NUMBER#\"<\/span>,\n \"X-nl-skv-version\"<\/span>: 869022424,\n \"X-nl-skv-timestamp\"<\/span>: 1326038279000,\n \"X-nl-service-timestamp\"<\/span>: 1326038279825\n },\n \"payload\"<\/span>: {\n \"current_temperature\"<\/span>: 19.98,\n \"hvac_fan_state\"<\/span>: false<\/span>,\n \"name\"<\/span>: \"TWO\"<\/span>, \"hvac_heat_x2_state\"<\/span>: false<\/span>,\n \"hvac_ac_state\"<\/span>: false<\/span>,\n \"can_cool\"<\/span>: true<\/span>,\n \"auto_away\"<\/span>: 0,\n \"compressor_lockout_enabled\"<\/span>: false<\/span>,\n \"target_temperature_low\"<\/span>: 16.66667,\n \"target_temperature_high\"<\/span>: 26.66667,\n \"compressor_lockout_timeout\"<\/span>: 0,\n \"hvac_heater_state\"<\/span>: false<\/span>,\n \"hvac_aux_heater_state\"<\/span>: false<\/span>,\n \"target_temperature\"<\/span>: 19.44444,\n \"can_heat\"<\/span>: true<\/span>,\n \"target_temperature_type\"<\/span>: \"heat\"<\/span>,\n \"target_change_pending\"<\/span>: true<\/span>\n }\n });<\/pre>\nEverything above is needed to update the current state of the UI. As you can see, the current temperature (returned as Celsius apparently) is 19.98 (67.964\u00b0F). The current temperature as displayed on the thermostat and the web UI was 68.<\/p>\n
Seeing these return values makes me think that they may be using Ruby and Rails (as the naming convention tends to follow Rails naming using underscores between words). I know for example, I wouldn\u2019t name variables\/columns that way when building a C#\/JavaScript MVC project.<\/em><\/p>\nRather than just a delta payload of what\u2019s changed, they\u2019ve currently opted for a full update of all information related to the thermostat state. <\/span><\/p>\nSeveral seconds later, a much larger payload was returned to a subscribe <\/strong>request:<\/span><\/p>\n\"status\"<\/span>: 200,\n\"headers\"<\/span>: {\n \"X-nl-skv-key\"<\/span>: \"device.#DEVICE 2 SERIAL NUMBER#\"<\/span>,\n \"X-nl-skv-version\"<\/span>: -2086438581,\n \"X-nl-skv-timestamp\"<\/span>: 1326038378000,\n \"X-nl-service-timestamp\"<\/span>: 1326038379023\n},\n\"payload\"<\/span>: {\n \"ob_orientation\"<\/span>: \"O\"<\/span>,\n \"upper_safety_temp\"<\/span>: 1000.0,\n \"forced_air\"<\/span>: true<\/span>,\n \"creation_time\"<\/span>: 1324142042019,\n \"switch_preconditioning_control\"<\/span>: false<\/span>,\n \"click_sound\"<\/span>: \"on\"<\/span>,\n \"leaf\"<\/span>: false<\/span>, \"user_brightness\"<\/span>: \"auto\"<\/span>,\n \"learning_state\"<\/span>: \"steady\"<\/span>,\n \"heat_pump_comp_threshold\"<\/span>: -1000.0,\n \"local_ip\"<\/span>: \"10.0.0.205\"<\/span>,\n \"backplate_serial_number\"<\/span>: \"#SHOULD BE DEVICE 2 SERIAL NUMBER, BUT ISN'T?#\"<\/span>,\n \"capability_level\"<\/span>: 1.03,\n \"postal_code\"<\/span>: \"#POSTALCODE#\"<\/span>,\n \"upper_safety_temp_enabled\"<\/span>: false<\/span>,\n \"heat_pump_aux_threshold\"<\/span>: 10.0,\n \"lower_safety_temp_enabled\"<\/span>: true<\/span>,\n \"serial_number\"<\/span>: \"#DEVICE 2 SERIAL NUMBER#\"<\/span>,\n \"temperature_lock\"<\/span>: false<\/span>,\n \"learning_time\"<\/span>: 1002,\n \"current_version\"<\/span>: \"1.0.4\"<\/span>,\n \"model_version\"<\/span>: \"Diamond-1.10\"<\/span>,\n \"backplate_bsl_info\"<\/span>: \"BSL\"<\/span>,\n \"auto_away_enable\"<\/span>: true<\/span>,\n \"heat_pump_comp_threshold_enabled\"<\/span>: false<\/span>,\n \"fan_mode\"<\/span>: \"auto\"<\/span>,\n \"range_enable\"<\/span>: false<\/span>,\n \"temperature_scale\"<\/span>: \"F\"<\/span>,\n \"backplate_mono_info\"<\/span>: \"TFE (BP_DVT) 3.5.2 (ehs@ubuntu) 2011-11-05 12:00:00\"<\/span>,\n \"backplate_bsl_version\"<\/span>: \"1.1\"<\/span>,\n \"equipment_type\"<\/span>: \"gas\"<\/span>,\n \"range_mode\"<\/span>: false<\/span>,\n \"lower_safety_temp\"<\/span>: 7.0,\n \"has_fan\"<\/span>: true<\/span>,\n \"hvac_wires\"<\/span>: \"Heat,Cool,Fan,Common Wire,Rc\"<\/span>,\n \"learning_mode\"<\/span>: true<\/span>,\n \"away_temperature_high\"<\/span>: 32.0,\n \"switch_system_off\"<\/span>: false<\/span>,\n \"time_to_target\"<\/span>: 1326039444,\n \"away_temperature_low\"<\/span>: 14.444444444444445,\n \"current_humidity\"<\/span>: 45,\n \"mac_address\"<\/span>: \"#MACADDR#\"<\/span>,\n \"backplate_mono_version\"<\/span>: \"3.5.2\"<\/span>,\n \"has_aux_heat\"<\/span>: false<\/span>,\n \"type\"<\/span>: \"TBD\"<\/span>,\n \"hvac_pins\"<\/span>: \"W1,Y1,C,Rc,G\"<\/span>,\n \"has_heat_pump\"<\/span>: false<\/span>,\n \"heat_pump_aux_threshold_enabled\"<\/span>: true<\/span>,\n \"battery_level\"<\/span>: 3.945,\n \"target_time_confidence\"<\/span>: 1.0\n}<\/pre>\n <\/p>\n
A few things to note:<\/p>\n
\n- Upper_safety_temperature <\/strong>is just a bit beyond my comfort zone at 1832\u00b0F. I don\u2019t know why it\u2019s sending a value like that to the client, and why it\u2019s stupidly high.<\/li>\n
- The backplate serial number doesn\u2019t match with the thermostat according to the payload response. I don\u2019t know why this might be as I confirmed that the numbers matched through visual inspection of the device just now.<\/li>\n
- The majority of these details are exposed in one way or another in the details area of the web UI.<\/li>\n
- Time to target (payload.time_to_target) is unusual in that it\u2019s a JavaScript Date value, divided by 1000. So, in the example above, the time to target is: new Date(1326039444 * 1000).toString() = >”Sun Jan 08 2012 10:17:24 GMT-0600 (Central Standard Time)”<\/strong>Next, a payload is returned with the new status:\n
\"status\"<\/span>: 200,\n\"headers\"<\/span>: {\n \"X-nl-skv-key\"<\/span>: \"shared.#DEVICE 2 SERIAL NUMBER#\"<\/span>,\n \"X-nl-skv-version\"<\/span>: 1689916148,\n \"X-nl-skv-timestamp\"<\/span>: 1326038378000,\n \"X-nl-service-timestamp\"<\/span>: 1326038379151\n},\n\"payload\"<\/span>: {\n \"hvac_fan_state\"<\/span>: false<\/span>,\n \"name\"<\/span>: \"TWO\"<\/span>,\n \"hvac_heat_x2_state\"<\/span>: false<\/span>,\n \"hvac_ac_state\"<\/span>: false<\/span>,\n \"can_cool\"<\/span>: true<\/span>,\n \"auto_away\"<\/span>: 0,\n \"compressor_lockout_enabled\"<\/span>: false<\/span>,\n \"target_temperature_low\"<\/span>: 16.66667,\n \"current_temperature\"<\/span>: 19.53,\n \"target_temperature_high\"<\/span>: 26.66667,\n