staromeste / homebridge-http-advanced-accessory

Supports all devices on HomeBridge Platform / Bridges devices to http
Apache License 2.0
65 stars 22 forks source link

Unexpected token M in JSON at position 0 #29

Open lapixo opened 3 years ago

lapixo commented 3 years ago

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 } } ],

staromeste commented 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 .

lapixo commented 3 years ago

Yes, i think the api return a http error or something else.

I would enable the debug an wait for the next error.

shanemcw commented 3 years ago

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 + "\"");
      }
shanemcw commented 3 years ago

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.

shanemcw commented 3 years ago

Screen Shot 2021-06-28 at 12 24 37 PM

staromeste commented 3 years ago

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 .

shanemcw commented 3 years ago

@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!

shanemcw commented 2 years ago

@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.

shanemcw commented 2 years ago

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.

shanemcw commented 2 years ago

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"
shanemcw commented 2 years ago

@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!

staromeste commented 2 years ago

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>

shanemcw commented 1 year ago

Pull requested!

shanemcw commented 9 months ago

Fixed in 1.3.0.