Open lapixo opened 3 years ago
You should enable the debug flag so we can see what you get from the device. It seems that you are not getting a valid JSON.
On Fri, 15 Jan 2021 at 08:38, lapixo notifications@github.com wrote:
I got periodically this error after hours: SyntaxError: Unexpected token M in JSON at position 0 at JSON.parse () at JPathMapper.self.map (/home/hoobs/.hoobs/node_modules/homebridge-http-advanced-accessory/mappers.js:87:19) at /home/hoobs/.hoobs/node_modules/homebridge-http-advanced-accessory/index.js:158:28
Version 1.1.23
This is my config { "accessory": "HttpAdvancedAccessory", "service": "TemperatureSensor", "name": "Temperatur-Kessel-Rücklauf", "forceRefreshDelay": 35, "debug": false, "urls": { "getCurrentTemperature": { "url": " http://stromlogger.local/data/c1a454a0-50eb-11eb-b605-6f3b0849b596.json?from=now", "mappers": [ { "type": "jpath", "parameters": { "jpath": "$.data.average" } } ] } }, "plugin_map": { "plugin_name": "homebridge-http-advanced-accessory", "index": 0 } }, { "accessory": "HttpAdvancedAccessory", "service": "TemperatureSensor", "name": "Temperatur-Kessel-Aussen", "forceRefreshDelay": 40, "debug": false, "urls": { "getCurrentTemperature": { "url": " http://stromlogger.local/data/83103160-51a1-11eb-927d-6b541f75fb16.json?from=now", "mappers": [ { "type": "jpath", "parameters": { "jpath": "$.data.average" } } ] } }, "plugin_map": { "plugin_name": "homebridge-http-advanced-accessory", "index": 0 } }, { "accessory": "HttpAdvancedAccessory", "service": "TemperatureSensor", "name": "Temperatur-Kessel-Ruecklauf", "forceRefreshDelay": 45, "debug": false, "urls": { "getCurrentTemperature": { "url": " http://stromlogger.local/data/a7d437f0-50eb-11eb-a75b-e3fc496a0075.json?from=now", "mappers": [ { "type": "jpath", "parameters": { "jpath": "$.data.average" } } ] } }, "plugin_map": { "plugin_name": "homebridge-http-advanced-accessory", "index": 0 } }, { "accessory": "HttpAdvancedAccessory", "service": "TemperatureSensor", "name": "Temperatur-Trinkwasser", "forceRefreshDelay": 50, "debug": false, "urls": { "getCurrentTemperature": { "url": " http://stromlogger.local/data/0b5ff770-55fd-11eb-a36f-17b99ceb0b99.json?from=now", "mappers": [ { "type": "jpath", "parameters": { "jpath": "$.data.average" } } ] } }, "plugin_map": { "plugin_name": "homebridge-http-advanced-accessory", "index": 0 } } ],
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/staromeste/homebridge-http-advanced-accessory/issues/29, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABBP2MOJKHWXTQCJ4EIVBNDSZ7WG7ANCNFSM4WDU4HAA .
Yes, i think the api return a http error or something else.
I would enable the debug an wait for the next error.
A data point—I saw this also a few days ago. Only saw this once.
SyntaxError: Unexpected token C in JSON at position 0 at JSON.parse ()
Note the 'C' instead of the 'M' in the previous report. Points to perhaps error text returned when JSON expected. Causes a SIGTERM and restart of Homebridge.
reference https://nodejs.org/en/knowledge/errors/what-is-try-catch/:
In the core Node.js libraries, the only place that one really needs to use a try-catch is around JSON.parse().
To prevent SIGTERM perhaps something like
try {
var result;
var json = JSON.parse(value);
if (json && typeof json === "object") {
result = JSONPath({path: self.jpath, json: json});
} else {
// self.log("expected JSON, got \"" + value + "\"");
}
}
catch (e) {
// self.log("expected JSON, got \"" + value + "\"");
}
I confirmed that if the response from the device is an error message instead of valid JSON, the error thrown by parse will SIGTERM causing Homebridge to restart. I can now create this error on demand. If the device continues to respond with non-JSON error messages, Homebridge will get stuck in a restart loop.
In my example, non-JSON error text is returned instead when the web server is running, but the service that provides the device data to the web server is not running.
You should make sure the device is responding with a valid json first.
On Tue, 29 Jun 2021 at 23:24, Shane McWhorter @.***> wrote:
[image: Screen Shot 2021-06-28 at 12 24 37 PM] https://user-images.githubusercontent.com/60005659/123869220-b5e66480-d8fe-11eb-83cd-5c30f9c0ac90.png
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/staromeste/homebridge-http-advanced-accessory/issues/29#issuecomment-870928899, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABBP2MLNCJJXFZ5ME7HBNVLTVI2YBANCNFSM4WDU4HAA .
@staromeste Thanks for the quick follow-up! I can see that devices in an error state may not send valid JSON as data—understandable if users do not have access to a device's source code. The nodejs.org's recommendation to wrap .parse in a 'try' seems to make some sense at first glance. In this case, invalid JSON SIGTERMS the whole Homebridge. The Homebridge recommendation that a plugin internally handles all errors that otherwise will cause a SIGTERM seems to make some sense at first glance. Thanks again!
@lapixo I found time to add a few lines of code to JPathMapper
in mappers.js to map SIGTERM-causing bad JSON data from a device to null, and to getDispatch
in index.js to ignore the null and not set the state at that time. I'll forward after a burn-in period of testing.
My device occasionally replies with "Connection refused" instead of valid JSON, causing a restart loop of Homebridge.
@lapixo I crafted a hot fix that is working for me so far.
In mappers.js
I replaced function JPathMapper
with the following
function JPathMapper(parameters) {
var self = this;
self.jpath = parameters.jpath;
self.index = parameters.index || 0;
self.map = function(value) {
var result = 'inconclusive';
var json;
try {
json = JSON.parse(value);
} catch (e) {
return result;
}
if (typeof json !== 'object') {
return result;
} else {
result = JSONPath({path: self.jpath, json: json});
if (result instanceof Array && result.length > self.index) {
result = result[self.index];
}
if (result instanceof Object) {
result = JSON.stringify(result);
}
}
return result;
}
}
and replaced the 3 lines 230
-232
in index.js
with
if(state == "inconclusive") {
this.log(`Inconclusive mapping of response "${responseBody}"`);
if (action.inconclusive){
this.debugLog("Response inconclusive and trying the action specified for this condition.");
getDispatch(callback,action.inconclusive);
} else {
this.debugLog("Response inconclusive with no further action specified for this condition.");
}
In my setup, these files are found in /usr/lib/node_modules/homebridge-http-advanced-accessory
and I sudo edit them.
e.g. this is how the hot fix handles and logs errors returned when JSON was expected:
[8/4/2021, 11:50:15 AM] [homebridge-http-advanced-accessory] This plugin slows down Homebridge. The read handler for the characteristic 'On' was slow to respond! See https://git.io/JtMGR for more info.
[8/4/2021, 11:50:15 AM] [homebridge-http-advanced-accessory] This plugin slows down Homebridge. The read handler for the characteristic 'On' was slow to respond! See https://git.io/JtMGR for more info.
[8/4/2021, 11:50:16 AM] [Dining Room Light] Inconclusive mapping of response ""
[8/4/2021, 11:50:16 AM] [Couch Lights] Inconclusive mapping of response ""
[8/4/2021, 11:50:16 AM] [Sleep] Inconclusive mapping of response ""
[8/4/2021, 11:50:16 AM] [Enable Chime] Inconclusive mapping of response ""
[8/4/2021, 11:50:16 AM] [Bedroom Lights] Inconclusive mapping of response ""
[8/4/2021, 11:50:16 AM] [Eve String] Inconclusive mapping of response "Connection timed out"
[8/4/2021, 11:50:16 AM] [Fence String] Inconclusive mapping of response "Connection timed out"
[8/4/2021, 11:50:16 AM] [Pool Light] Inconclusive mapping of response "Connection timed out"
[8/4/2021, 11:50:16 AM] [Florida Room North Lights] Inconclusive mapping of response "Connection timed out"
[8/4/2021, 11:50:17 AM] [Florida Room South Lights] Inconclusive mapping of response "Connection timed out"
@staromeste I've been testing this fix since August 2021—looks stable and prevents the plugin from crashing on bad data from a device. Would you like me to pull request? Thanks either way!
Yes please!
On Mon, 18 Apr 2022 at 19:44, Shane McWhorter @.***> wrote:
@staromeste https://github.com/staromeste I've been testing this fix since August 2021—looks stable and prevents the plugin from crashing on bad data from a device. Would you like me to pull request? Thanks either way!
— Reply to this email directly, view it on GitHub https://github.com/staromeste/homebridge-http-advanced-accessory/issues/29#issuecomment-1101600459, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABBP2MN3ITIX73E2SPWK5YLVFWNQZANCNFSM4WDU4HAA . You are receiving this because you were mentioned.Message ID: @.*** .com>
Pull requested!
Fixed in 1.3.0.
I got periodically this error after hours: SyntaxError: Unexpected token M in JSON at position 0 at JSON.parse ()
at JPathMapper.self.map (/home/hoobs/.hoobs/node_modules/homebridge-http-advanced-accessory/mappers.js:87:19)
at /home/hoobs/.hoobs/node_modules/homebridge-http-advanced-accessory/index.js:158:28
Solution: There should be a validation, if the result is a json object...
Version 1.1.23
This is my config
{ "accessory": "HttpAdvancedAccessory", "service": "TemperatureSensor", "name": "Temperatur-Kessel-Rücklauf", "forceRefreshDelay": 35, "debug": false, "urls": { "getCurrentTemperature": { "url": "http://stromlogger.local/data/c1a454a0-50eb-11eb-b605-6f3b0849b596.json?from=now", "mappers": [ { "type": "jpath", "parameters": { "jpath": "$.data.average" } } ] } }, "plugin_map": { "plugin_name": "homebridge-http-advanced-accessory", "index": 0 } }, { "accessory": "HttpAdvancedAccessory", "service": "TemperatureSensor", "name": "Temperatur-Kessel-Aussen", "forceRefreshDelay": 40, "debug": false, "urls": { "getCurrentTemperature": { "url": "http://stromlogger.local/data/83103160-51a1-11eb-927d-6b541f75fb16.json?from=now", "mappers": [ { "type": "jpath", "parameters": { "jpath": "$.data.average" } } ] } }, "plugin_map": { "plugin_name": "homebridge-http-advanced-accessory", "index": 0 } }, { "accessory": "HttpAdvancedAccessory", "service": "TemperatureSensor", "name": "Temperatur-Kessel-Ruecklauf", "forceRefreshDelay": 45, "debug": false, "urls": { "getCurrentTemperature": { "url": "http://stromlogger.local/data/a7d437f0-50eb-11eb-a75b-e3fc496a0075.json?from=now", "mappers": [ { "type": "jpath", "parameters": { "jpath": "$.data.average" } } ] } }, "plugin_map": { "plugin_name": "homebridge-http-advanced-accessory", "index": 0 } }, { "accessory": "HttpAdvancedAccessory", "service": "TemperatureSensor", "name": "Temperatur-Trinkwasser", "forceRefreshDelay": 50, "debug": false, "urls": { "getCurrentTemperature": { "url": "http://stromlogger.local/data/0b5ff770-55fd-11eb-a36f-17b99ceb0b99.json?from=now", "mappers": [ { "type": "jpath", "parameters": { "jpath": "$.data.average" } } ] } }, "plugin_map": { "plugin_name": "homebridge-http-advanced-accessory", "index": 0 } } ],