11 Replies Latest reply on Oct 19, 2015 2:15 AM by Marcin-Makowski

    Issue Sending Data to enableiot.com

    Unn

      I have several Galileo Gen 1s running yocto linux with a clone from a working Gen 1 board. The working system whose SD card I cloned runs a simple python script the sends data via UDP to the iotkit-agent and up to enableiot.com via mqtt, and the data appears in the charts area.

       

      I configured each of the new boards differently (ie, different hostnames, device names, ids, etc) and added them to enableiot.com; also adding a few components for each via the iotkit-admin. My devices and components all appear in the web interface. I start up the iotkit-agent on all the boards (after connecting them to the internet) and run the script to send data to the cloud.... And none of the data gets there! To ensure this is the case and not the web interface running into problems, I tried using the REST API to pull the data down myself which is successful for the working master node, but all the new nodes again have no data.

       

      Checking the logs of the agent, all seem well:

       

      root@ICRI_107:~# systemctl status iotkit-agent -l -n100
      ● iotkit-agent.service - iotkit-agent
         Loaded: loaded (/lib/systemd/system/iotkit-agent.service; enabled)
         Active: active (running) since Mon 2015-09-28 16:34:13 UTC; 22h ago
      Main PID: 147 (node)
         CGroup: /system.slice/iotkit-agent.service
                 └─147 node /usr/bin/iotkit-agent
      
      
      Sep 29 15:16:43 ICRI_107 iotkit-agent[147]: 2015-09-29T15:16:43.599Z - info: Submitting:  v=26.604241807445362, n=ss_temp
      Sep 29 15:16:43 ICRI_107 iotkit-agent[147]: 2015-09-29T15:16:43.628Z - info: Submitting:  v=37.97429180514538, n=ss_humid
      Sep 29 15:16:43 ICRI_107 iotkit-agent[147]: 2015-09-29T15:16:43.649Z - info: Submitting:  v=0.6246871434512636, n=ss_no2
      Sep 29 15:16:43 ICRI_107 iotkit-agent[147]: 2015-09-29T15:16:43.668Z - info: Submitting:  v=4.545079549139133, n=ss_light
      Sep 29 15:16:43 ICRI_107 iotkit-agent[147]: 2015-09-29T15:16:43.688Z - info: Submitting:  v=0.15197704187725636, n=ss_co
      Sep 29 15:16:43 ICRI_107 iotkit-agent[147]: 2015-09-29T15:16:43.777Z - info: Response received:  status=0
      Sep 29 15:16:43 ICRI_107 iotkit-agent[147]: 2015-09-29T15:16:43.933Z - info: Response received:  status=0
      Sep 29 15:16:43 ICRI_107 iotkit-agent[147]: 2015-09-29T15:16:43.941Z - info: Response received:  status=0
      Sep 29 15:16:43 ICRI_107 iotkit-agent[147]: 2015-09-29T15:16:43.948Z - info: Response received:  status=0
      Sep 29 15:16:43 ICRI_107 iotkit-agent[147]: 2015-09-29T15:16:43.951Z - info: Response received:  status=0
      Sep 29 15:17:40 ICRI_107 iotkit-agent[147]: 2015-09-29T15:17:40.221Z - info: Submitting:  v=26.604241807445362, n=ss_temp
      Sep 29 15:17:40 ICRI_107 iotkit-agent[147]: 2015-09-29T15:17:40.250Z - info: Submitting:  v=37.97429180514538, n=ss_humid
      ...
      

       

      Running iotkit-admin test succeeds and even sending an observation to the cloud via the iotkit-admin seems fine:

       

      root@ICRI_107:~# iotkit-admin observation ss_no2 0.05
      2015-09-29T15:29:54.476Z - info: Trying to disconnect
      2015-09-29T15:29:54.659Z - info: Submitting:  n=ss_no2, v=0.05
      2015-09-29T15:29:54.717Z - info: Trying with Secure Connection tobroker.us.enableiot.com:8883
      2015-09-29T15:29:54.937Z - info: Waiting for MQTTConnector to connect # 1
      2015-09-29T15:29:56.008Z - info: MQTTConnector: Connection successful to broker.us.enableiot.com:8883
      2015-09-29T15:29:56.214Z - info: Response received:  status=0
      2015-09-29T15:29:56.224Z - info: Observation Sent status=0
      root@ICRI_107:~# iotkit-admin test
      2015-09-29T15:30:52.640Z - info: Trying to connect to host ...
      2015-09-29T15:30:52.748Z - info: Starting Health testing
      2015-09-29T15:30:52.778Z - info: Trying with Secure Connection tobroker.us.enableiot.com:8883
      2015-09-29T15:30:53.000Z - info: Waiting for MQTTConnector to connect # 1
      2015-09-29T15:30:54.398Z - info: MQTTConnector: Connection successful to broker.us.enableiot.com:8883
      2015-09-29T15:30:54.916Z - info: STATUS: device/ICRI_107_GALILEO/health kind=healthcheck, isHealthy=true, currentSetting=PROD, name=iotkit-gateway, build=0.14.2, date=2015-07-30T11:17:01.395Z, items=[connected=true]
      2015-09-29T15:30:54.943Z - info: Fired STATUS: %sdevice/ICRI_107_GALILEO/health{"kind":"healthcheck","isHealthy":true,"currentSetting":"PROD","name":"iotkit-gateway","build":"0.14.2","date":"2015-07-30T11:17:01.395Z","items":[{"broker":{"connected":true}}]}
      2015-09-29T15:30:54.965Z - info: Connected to broker.us.enableiot.com
      2015-09-29T15:30:54.973Z - info: Environment: PROD
      2015-09-29T15:30:54.978Z - info: Build: 0.14.2
      

       

      So, Im a bit confused what is going wrong.... Any help would be appreciated!

        • 1. Re: Issue Sending Data to enableiot.com
          PabloM_Intel

          Hi Unn,

           

          1. Could you tell us how did you clone the systems so we can reproduce your issue? Did you follow a guide or tutorial?
          2. Which image are you using? uClibc or eglibc based?


          It seems to be a problem with the cloning process because the original does work. We would appreciate if you could also share the python script that you’re using.

           

          Regards,

          PabloM_Intel

          • 2. Re: Issue Sending Data to enableiot.com
            Unn

            Pablo,

             

            To clone the system, I took the SD card which contained the linux image on the working Galileo, put into my Windows machine, used Win32DiskImager to create an image file, then took an new SD card and wrote that same image out, creating a duplicate of the Galileo's linux system. I did go in and change a few things by hand as mentioned above. Not sure what could have gone wrong such that everything seems fine but the enableiot doesnt store the data.... (seems strange it responses to the mqtt correctly, as the global.json file says QoS = 1, so it should require acknowledgements to the publish messages it is sending, so it seems like enableiot is acknowledging the messages but not actually storing them)

             

            I did build my own version of the kernel using the BSP to include cp210x drivers. Heres the result of uname -a:

             

            Linux ICRI_107 3.8.7-yocto-standard #2 Thu Aug 27 04:45:45 PDT 2015 i586 GNU/Linux

             

            Note this is based off the iot devkit, so Im pretty sure it uses eglibc.

             

            Heres the python script which reads data from sensors connected to the Galileo and tries to push them to enableiot (note that it uses my modules to simplify the interface):

             

            #!/usr/bin/python
            
            
            #
            # IoTNode Script
            #
            # Runs a node with a given configuration (from file)
            #
            # Michael Rosen
            # mrrosen
            # 07-07-2015
            #
            
            
            # Imports
            import sys
            import json
            import time
            import getopt
            
            
            # Senors imports
            import DavisWS
            import ScienceScopeMulti
            
            
            # IoT platform imports
            import IoTAnalytics
            
            
            # Print commands
            def printInfo(s):
              print("-I- %s" % s);
            
            def printWarn(s):
              print("-W- %s" % s);
            
            def printError(s):
              print("-E- %s" % s);
            
            def printDebug(s, d):
              if (d):
                print("-D- %s" % s);
            
            
            def printHelp():
              print(" iotnode.py\n"
                    "\n"
                    "  Script for running IoTNodes with a provided configuration file\n"
                    "\n"
                    "  Arguments:\n"
                    "\n"
                    "    -h, --help              Displays this text.\n"
                    "    -c, --config [file]      Needed to provide the script with a configuration file for\n"
                    "                              telling this node which sensors are connected and which IoT\n"
                    "                              platform to use (also some configuration on each of these).\n"
                    "                              Note that this should be a JSON file\n"
                    "    -d, --debug              Print debug messages\n");
            
              
            
            def main(argv):
            
              # Parse arguments
              try:
                (options, args) = getopt.getopt(argv, 'hdc:', ['config=', 'help', 'debug']);
              except:
                printError("Bad commandline options");
                print('');
                printHelp();
                sys.exit(-1);
            
            
              configFile = '';
              debug = False;
            
            
              if (not(options[0])):
                printError("Bad commandline options");
                print('');
                printHelp();
                sys.exit(-1);
            
              for (o, a) in options:
                if (o in ("-h", "--help")):
                  printHelp();
                  sys.exit(0);
                elif (o in ("-c", "--config")):
                  configFile = a;
                elif (o in ("-d", "--debug")):
                  debug = True;
            
              if (configFile == ''):
                printError("Need a configuration file!");
                sys.exit(-1);
            
              # Load configuration
              with open(configFile) as configFP:
                config = json.load(configFP);
            
              printInfo("Configuration file loaded!");
            
              # Get the sleep time
              sleepTime = config['sleep'];
            
              # Get median sample and interval
              sampleNum = config['sampleNum'];
              sampleInterval = config['sampleInterval'];
            
              printDebug("Node properties: sleepTime = %d, sampleNum = %d, sampleInterval = %d" % (sleepTime, sampleNum, sampleInterval), debug);
            
              # Connect/initialize any sensors
              sensors = [];
              for s in config['sensors']:
                if (s['type'] == 'DavisWS'):
                  # Add a Davis Weather Station
                  sensors.append({'type': s['type'],
                                  'sensor': DavisWS.DavisWeatherStation(s['port'], s['precision']),
                                  'params': s['sensors']});
                  printDebug("Found DWS sensor: %s %s %d" % (s['type'], s['port'], s['precision']), debug);
                elif (s['type'] == 'ScienceScopeMulti'):
                  # Add a ScienceScope sensor expansion board
                  scope = ScienceScopeMulti.ScienceScopeMulti(s['precision']);
                
                  if (debug):
                    printDebug("ScienceScopeMulti Enumeration (before check and fix):", debug);
                    scope.enumerate();
                
                  # Check to make sure the sensors enumerated correctly, if not, just override
                  for ss in s['sensors']:
                    if ((scope.sensors[ss['port']].id != ss['id']) or
                        (scope.sensors[ss['port']].range != ss['range'])):
                      scope.sensors[ss['port']] = ScienceScopeMulti.ScienceScopeMulti.Sensor(ss['id'],
                                                                                              ss['range'],
                                                                                              ss['port'],
                                                                                              scope);
                                                                                            
                  if (debug):
                    printDebug("ScienceScopeMulti Enumeration (after check and fix):", debug);
                    scope.enumerate();
                
                  sensors.append({'type': s['type'],
                                  'sensor': scope,
                                  'params': s['sensors']});
                  printDebug("Found Science sensor: %s %d" % (s['type'], s['precision']), debug);
                else:
                  printWarn("Unknown sensor provided: %s" % s['type']);
            
              if (not(sensors)):
                printError("No valid sensors were found!");
                sys.exit(-2);
            
              printInfo("Sensors from configuration initialized!");
            
              # Connect/initialize any IoT
              iot = [];
              for i in config['iot']:
                if (i['type'] == 'IoTAnalytics'):
                  iot.append({'type': i['type'], 'iot': IoTAnalytics.IoTAnalytics()});
                  printDebug("IoTAnaltyics found: %s" % i['type'], debug);
                else:
                  printWarn("Unknown IoT platform provided: %s" % i['type']);
                
              if (not(iot)):
                printError("No valid IoT platform was found!");
                sys.exit(-2);
              
              printInfo("IoT platforms from configuration initialized!");
            
              while (True):
            
                # Collect data from all the sensors
                printInfo("Reading from sensors...");
              
                data = [];
              
                for s in sensors:
                  if (s['type'] == 'DavisWS'):
                    # Any data from the DWS so long as it is in the sensor list (take median)
                    samples = dict();
                    for ss in s['params']:
                      samples[ss['name']] = [];
                  
                    for sample in xrange(sampleNum):
                      s['sensor'].update();
                    
                      for ss in s['params']:
                        if ('data' in ss):
                          value = s['sensor'].data[ss['data']];
                          printDebug("Sample for %s:%s = %10.6f" % (ss['name'], ss['data'], value), debug);
                        elif ('status' in ss):
                          value = s['sensor'].status[ss['status']];
                          printDebug("Sample for %s:%s = %10.6f" % (ss['name'], ss['status'], value), debug);
                        else:
                          printError("%s is missing a valid data/status name!" % ss['name']);
                          sys.exit(-5);
                      
                        samples[ss['name']].append(value);
                      
                      time.sleep(sampleInterval);
                  
                    for ss in samples:
                      samples[ss].sort();
                      samples[ss] = samples[ss][sampleNum / 2];
                      printDebug("Median for %s = %10.6f" % (ss, samples[ss]), debug);
                  
                    for ss in s['params']:
                      data.append({'name': ss['name'],
                                  'value': (samples[ss['name']] * ss['factor'])});
                  elif (s['type'] == 'ScienceScopeMulti'):
                    # Any data from the ScienceScope sensors
                    samples = dict();
                    for ss in s['params']:
                      samples[ss['name']] = [];
                    
                    for ss in s['params']:
                      for sample in xrange(sampleNum):
                        value = s['sensor'].sensors[ss['port']].read();
                        samples[ss['name']].append(value);
                        printDebug("Sample for %s:%d = %10.6f" % (ss['name'], ss['port'], value), debug);
                      
                        time.sleep(sampleInterval);
                    
                    for ss in samples:
                      samples[ss].sort();
                      samples[ss] = samples[ss][sampleNum / 2];
                      printDebug("Median for %s = %10.6f" % (ss, samples[ss]), debug);
                    
                    for ss in s['params']:
                      data.append({'name': ss['name'],
                                  'value': (samples[ss['name']] * ss['factor'])});
              
                # Send collected data to IoT platforms
                printInfo("Sensors read, sending to IoT platform(s)...");
                printDebug("Data set to send = %s" % data, debug);
              
                for i in iot:
                  for d in data:
                    if (i['type'] == 'IoTAnalytics'):
                      i['iot'].sendData(d['name'], d['value']);
                      printDebug("Send data %10.6f to %s" % (d['value'], d['name']), debug);
              
                # Sleep for a given time
                printInfo("Data sent! Sleeping for %d seconds..." % sleepTime);
                time.sleep(sleepTime);
            
            
            if __name__ == "__main__":
              main(sys.argv[1:]);
            
            

             

            Code from IoTAnalytics module:

            #
            # Intel IoT Analytics Class
            #
            # Class that transfers data to and from the Intel IoT Analytics platform via the iotkit-agent
            #
            # Michael Rosen
            # mrrosen
            # 24-08-2015
            #
            
            
            import json
            import socket
            
            
            class IoTAnalytics(object):
            
            
              connHost = "127.0.0.1";
              connSendPort = 41234;
              connRecvPort = 41235;
            
              def __init__(self):
                self.connSendSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);
                self.connRecvSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);
                self.connRecvSock.bind((self.connHost, self.connRecvPort));
            
              # Adds a new component to the IoT data store dashboard
              def register(self, rname, rtype):
                jsonMsg = {
                  "n": rname,
                  "t": rtype
                };
               
                self.connSendSock.sendto(json.dumps(jsonMsg), (self.connHost, self.connSendPort));
               
              # Sends datapoint to the IoT data store
              def sendData(self, dname, dvalue):
                jsonMsg = {
                  "n": dname,
                  "v": dvalue
                };
               
                self.connSendSock.sendto(json.dumps(jsonMsg), (self.connHost, self.connSendPort));
               
              # Retrieves data from the IoT data store
              def recvData(self, dname, timeout):
                self.connRecvSock.settimeout(timeout);
                while True:
                  try:
                    (data, addr) = self.connRecvSock.recvfrom(4096);
                  except:
                    return None;
                  if (addr[0] == "127.0.0.1"):
                    break;
                   
                js = json.loads(data);
               
                cname = js["component"];
                argv = js["argv"];
               
                if (dname == cname):
                  return argv;
            
            
            • 3. Re: Issue Sending Data to enableiot.com
              Marcin-Makowski

              Hi Unn,

              In order to help you with this issue I need to clarify some things

              1. I assume that you don't see your data in dashboard.us.enableiot.com in chart tab ?

              2. Does your Total number of observations (which can be seen here:https://dashboard.us.enableiot.com/ui/dashboard#/board after clicking gear icon, Observation period -> total) don't match for all devices?

              3. If you go to chart tab and select your new deivce and its component, then if you choose time period "last year" are you still not seeing any data?

              4. It's unclear for me when you refering to master node and new node. What is the difference between working node and new nodes?

               

               

              Can you please attach some agent logs from /tmp/agent.log (or other directory if that was changed)

               

              Best regards

              Marcin

              • 4. Re: Issue Sending Data to enableiot.com
                Unn

                Marcin,

                 

                1. That is correct, I see no data in the charts. I have even used the REST API for enableiot to attempt to pull data directly (with a python script that can successfully pull down data from a working node) and get no observations back.

                 

                2. The total observations reported by the dashboard is 0 for the project containing my new nodes (note that the working node is a member of a different project).

                 

                3. Displaying the chart for all components from any of the nodes and setting the chart to include data from the last year results in "No data to show"

                 

                4. All the information I have given is from a new node. The original node (the one I cloned) still works fine. They are all running the above software and have the same version of yocto and other tools. The major differences are the names of the nodes and that all the new nodes are in a separate project ("account"). They were activated with the new account's activation code. Is it possible the agent is unaware of this change? And if the requests I am sending are faulty, why does it seem like the new nodes are getting ACK responses?

                 

                The agent.log file from a new node is attached:

                 

                Thanks

                • 5. Re: Issue Sending Data to enableiot.com
                  Marcin-Makowski

                  Hi again,

                   

                  You are using MQTT for sending data, so you are getting ACK from broker (information was received) but your message goes to queue and there maybe an issue there

                  (maybe broker is trying send data to other place than you expect).

                   

                  You can try changing "mqtt" to "rest" call and test that ("default_connector" in  global.json config which should be in /usr/lib/node_modules/iotkit-agent/config)

                  And then try to either restart iotkit-agent or just perform "iotkit-admin observation " to test if data will be stored that way. If your REST call will work then we will

                  need to investigate broker itself (in that case please provide me device_id)

                   

                  It is possible that you have activated again devices with new access code yet during activation they were attached to previous account.

                   

                  1. Please check if device-id is proper for account you are testing. Maybe device and its data are attached to other of your account.

                  2. If you did any change in agent config then you need to restart agent (systemctl restart iotkit-agent)

                   

                  Best way to check if everything is attached to proper endpoints and account is to do following steps:

                   

                  1. Locate your main config for agent (usualy /usr/lib/node_modules/iotkit-agent/config/global.json)

                  2. Check "data_directory" for path to device.json

                  3. Check device.json in "data_directory" and its:

                  3.1 "account_id" - please check that this is the same account_id that appears in your account tab

                  3.2  "device_id" - is it same as in your account?

                   

                  It may be hard to locate issue with your case but

                  since none of your new devices is sending data, you may want to try register device as new one in your account following this procedure

                  Please bear in mind doing so your device will no longer be attached to device you have in dashboard (it will apear as new device)

                   

                  1. systemctl stop iotkit-agent

                  2. iotkit-admin initialize

                  3. iotkit-admin set-device-id ProvideUniqueIdHere

                  4. iotkit-admin activate UseCodeFromYourAccount

                  5. register any components you need e.g.: iotkit-admin register temperature temperature.v1.0

                  6. send test observation: iotkit-admin observation temperature 30

                  7. Check in dashboard if device received observation

                  8. systemctl start iotkit-agent

                  9. Run again your script after registering all components


                  If registering device as new one won't work probably I will need more information


                  Thank you for your response

                  • 6. Re: Issue Sending Data to enableiot.com
                    Unn

                    After switching the node to REST and restarting the agent, the node sends data successfully. It looks like there is an issue in the mqtt request being sent to the broker. Could we do something to fix this as I rather use mqtt as my transfer protocol if possible?

                     

                    Thanks,

                    Mike

                    • 7. Re: Issue Sending Data to enableiot.com
                      Marcin-Makowski

                      Hi Mike,

                       

                      Thank you very much. We found we have an issue with mqtt broker which we will be fixing.

                       

                      For now broker accepts request from device that has the same gateway-id as device-id

                      Following workaround should work for you

                       

                      1. Update your device in dashboard setting gateway-id same as device-id

                      2. Update your device with agent : iotkit-admin set-gateway-id YourDeviceID

                       

                      if we checked right one of your device has following device-id and gateway-id

                       

                      gatewayId - ICRI

                      dewiceId - ICRI_113_GALILEO


                      So in this case changing in dashboard gatewayId to ICRI_113_GALILEO and  #> iotkit-admin set-gateway-id ICRI_113_GALILEO should help


                      Please let me know if that solved your issue.


                      Best regards

                      Marcin

                      • 8. Re: Issue Sending Data to enableiot.com
                        Unn

                        Marcin,

                         

                        Yep, that did it, mqtt now works with the device-id and gateway-id being the same. I do want to use gateway-id as a useful filter to group devices; so when will I be able to have different device-ids and gateway-ids for a device in mqtt again?

                         

                        Thanks,

                        Mike

                        • 9. Re: Issue Sending Data to enableiot.com
                          Marcin-Makowski

                          Hi Mike,

                           

                          I'm glad that it worked for you.

                          You can create tags and add tags to devices in dashboard to help you with filtering. This way you can even make advanced search to return data only for devices with sepcific tags.

                           

                          Right now we're not sure when we provide update to mqtt broker which allows different gateway-id and device-id names. I will let you know in this topic when it happens.

                           

                          Best regards

                          Marcin

                          • 10. Re: Issue Sending Data to enableiot.com
                            Unn

                            Thanks Marcin

                             

                            Tags seem an alright solution however, the Device page in the dashboard doesnt allow filtering by tag right now. Or at least while there is a filter box, I cant get the list to show only those tagged with my filter string (Im using Chrome on a Win8 machine; all other filters seem to work):

                             

                            enableiot_tag_issue.png

                            I do plan to pull down data using the REST API, so I can use the tags for that, but it would be nice to have the filter working on the dashboard...

                             

                            Thanks again,

                            Mike

                            • 11. Re: Issue Sending Data to enableiot.com
                              Marcin-Makowski

                              Hi Mike,

                              We did small fix on Tags searching in dashboard, hope it will help you. I know it's not perfect (can't filter by many tags), please remember page has still "beta" badge and we are more focused on REST API than page itself. If there will be any updates I will let you know.

                               

                              Best regards

                              Marcin