Accessing Parameter Value for Real Time POST Requests

Firmware/software/electronics/mechanics
Post Reply
mcheli
Beginner
Posts: 14
Joined: Fri Oct 02, 2015 7:48 pm

Accessing Parameter Value for Real Time POST Requests

Post by mcheli »

Hi!

So i've got a few CrazyFlies that i'm hoping to use to stream parameter values to a web server. The hope is to really make the quadcopters "IoT"ized, but to start I just want to send acceleration data.

I need to be able to repeatedly and quickly access a parameter and then send that data with a POST request. What i've tried so far...

Creating a log block that I write to file with the default Crazyflie PC software. I then used a java program to read the last line of the file and send that value. That worked great except that the file is not updated very rapidly. If I understand how it's working correctly, a group of values is written into the file every few seconds. This makes my last-line program only update with a new value every few seconds, which is not fast enough for me.

Which brings me to the question...

If I wanted to be able to access a parameter value constantly (or increase the speed that the csv file is written) how would I do that? I am also open to the idea of modifying crazyflie pc software so that this process happens automatically (although i'm not looking to do a lotttt of work).

The program I made is below...

Code: Select all

package file_read;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import file_read.SentToThingWorx;

public class FileReader {

	public static String readLastLine(String filename) throws IOException {
		FileInputStream in = new FileInputStream(filename);
		BufferedReader br = new BufferedReader(new InputStreamReader(in));

		String strLastLine = "";
		String tmp;

		while ((tmp = br.readLine()) != null)
		{
			strLastLine = tmp;
		}
		
		String[] strArray = strLastLine.split(",");
		
		System.out.println(strArray[1]);
		
		in.close();
		return strArray[1];

	}

	public static void main(String [] args) throws IOException{
		
		String filename = "D:/Users/mcheli/AppData/Roaming/cfclient/logdata/20151002T14-32-59/TWX_TEST-20151002T14-34-16.csv";
		
		while(true){
		SentToThingWorx.send(readLastLine(filename));
		}
	}

}

Code: Select all

package file_read;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class SentToThingWorx {

	public static void send (String Data) {
    	URL url;
		String urlToRead;
	    HttpURLConnection conn;
	    BufferedReader rd;
	      	String line;
	      	String result = "";
	    
	    urlToRead = "http://acadev1.cloud.thingworx.com/Thingworx/Things/jocox_training_thing/Services/Write?appKey=[omitted]&method=post&x-thingworx-session=true<&Data=" + Data; //Mark look here, change to my thingworx server
	    
	    try {
	    	url = new URL(urlToRead);
	    	conn = (HttpURLConnection) url.openConnection();
	         	conn.setRequestMethod("GET");
	         	rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
	         	while ((line = rd.readLine()) != null) {
            result += line;
	         	}
         rd.close();
	    } 
	    catch (Exception e) {
	    	e.printStackTrace();
	    }
	    System.out.println(result);	
	    return;
	}
}
tobias
Bitcraze
Posts: 2339
Joined: Mon Jan 28, 2013 7:17 pm
Location: Sweden

Re: Accessing Parameter Value for Real Time POST Requests

Post by tobias »

It could probably be done pretty simple in python instead. What about using one of the logging examples and in that add code to post it?

If you rather change the pc client to update the cvs more often you need to find where the write is being made and do a flush after every write so that it gets written to file directly. It might also be that it can't be controlled as the OS might decide when to write things to disc.
mcheli
Beginner
Posts: 14
Joined: Fri Oct 02, 2015 7:48 pm

Re: Accessing Parameter Value for Real Time POST Requests

Post by mcheli »

Thanks for the response!

That example looks very promising. My apologies for being a noob here, but can I ask more about the specific implementation of this example? How do I actually make it run in the environment?
mcheli
Beginner
Posts: 14
Joined: Fri Oct 02, 2015 7:48 pm

Re: Accessing Parameter Value for Real Time POST Requests

Post by mcheli »

Answered my own question, and for anyone who's referencing this later...

If you download the source for the crazyflie python client, there is a folder called "examples" with the code being referenced above "basiclog.py". After modification this code can be run by going to the examples folder in command line and running "python basiclog.py". This python file will automatically detect and connect to a nearby crazyflie and then execute the program.

Thanks so much for the help! I'm not quite done yet though...

Here's the function that gets the data and does a get request

Code: Select all

def _stab_log_data(self, timestamp, data, logconf):
        """Callback froma the log API when data arrives"""
        print data
        parameters = 'Data=' + str(data)
        print server + thing + servicecall + appKey + session + parameters
        r = requests.get(server + thing + servicecall + appKey + session + parameters)  
        print r
However when I actually run the code second two print statements don't happen. Any idea why?

Full code for reference:

Code: Select all

# -*- coding: utf-8 -*-

#

#     ||          ____  _ __

#  +------+      / __ )(_) /_______________ _____  ___

#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \

#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/

#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/

#

#  Copyright (C) 2014 Bitcraze AB

#

#  Crazyflie Nano Quadcopter Client

#

#  This program is free software; you can redistribute it and/or

#  modify it under the terms of the GNU General Public License

#  as published by the Free Software Foundation; either version 2

#  of the License, or (at your option) any later version.

#

#  This program is distributed in the hope that it will be useful,

#  but WITHOUT ANY WARRANTY; without even the implied warranty of

#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

#  GNU General Public License for more details.



#  You should have received a copy of the GNU General Public License

#  along with this program; if not, write to the Free Software

#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,

#  MA  02110-1301, USA.



"""

Simple example that connects to the first Crazyflie found, logs the Stabilizer

and prints it to the console. After 10s the application disconnects and exits.

"""



import sys

sys.path.append("../lib")



import cflib.crtp



import logging

import time

from threading import Timer



import cflib.crtp

from cfclient.utils.logconfigreader import LogConfig

from cflib.crazyflie import Crazyflie



import requests



# Only output errors from the logging framework

logging.basicConfig(level=logging.ERROR)



class LoggingExample:

    """

    Simple logging example class that logs the Stabilizer from a supplied

    link uri and disconnects after 5s.

    """

    def __init__(self, link_uri):

        """ Initialize and run the example with the specified link_uri """



        # Create a Crazyflie object without specifying any cache dirs

        self._cf = Crazyflie()



        #ThingWorx connection information

        server = 'http://acadev1.cloud.thingworx.com/Thingworx/Things/'

        thing = 'MicroQuad_Thing'

        servicecall = '/Services/Write?method=put&'

        appKey = 'appKey=4456a419-5b4d-4c8c-98a7-d88a1804f7ee'

        session = '&x-thingworx-session=true&'



        # Connect some callbacks from the Crazyflie API

        self._cf.connected.add_callback(self._connected)

        self._cf.disconnected.add_callback(self._disconnected)

        self._cf.connection_failed.add_callback(self._connection_failed)

        self._cf.connection_lost.add_callback(self._connection_lost)



        print "Connecting to %s" % link_uri



        # Try to connect to the Crazyflie

        self._cf.open_link(link_uri)



        # Variable used to keep main loop occupied until disconnect

        self.is_connected = True



    def _connected(self, link_uri):

        """ This callback is called form the Crazyflie API when a Crazyflie

        has been connected and the TOCs have been downloaded."""

        print "Connected to %s" % link_uri



        # The definition of the logconfig can be made before connecting

        self._lg_stab = LogConfig(name="Stabilizer", period_in_ms=10)

        self._lg_stab.add_variable("stabilizer.roll", "float")

        self._lg_stab.add_variable("stabilizer.pitch", "float")

        self._lg_stab.add_variable("stabilizer.yaw", "float")



        # Adding the configuration cannot be done until a Crazyflie is

        # connected, since we need to check that the variables we

        # would like to log are in the TOC.

        self._cf.log.add_config(self._lg_stab)

        if self._lg_stab.valid:

            # This callback will receive the data

            self._lg_stab.data_received_cb.add_callback(self._stab_log_data)

            # This callback will be called on errors

            self._lg_stab.error_cb.add_callback(self._stab_log_error)

            # Start the logging

            self._lg_stab.start()

        else:

            print("Could not add logconfig since some variables are not in TOC")



        # Start a timer to disconnect in 10s

        t = Timer(5, self._cf.close_link)

        t.start()



    def _stab_log_error(self, logconf, msg):

        """Callback from the log API when an error occurs"""

        print "Error when logging %s: %s" % (logconf.name, msg)



    def _stab_log_data(self, timestamp, data, logconf):

        """Callback froma the log API when data arrives"""

        print data

        parameters = 'Data=' + str(data)

        print server + thing + servicecall + appKey + session + parameters

        r = requests.get(server + thing + servicecall + appKey + session + parameters)  

        print r



    def _connection_failed(self, link_uri, msg):

        """Callback when connection initial connection fails (i.e no Crazyflie

        at the speficied address)"""

        print "Connection to %s failed: %s" % (link_uri, msg)

        self.is_connected = False



    def _connection_lost(self, link_uri, msg):

        """Callback when disconnected after a connection has been made (i.e

        Crazyflie moves out of range)"""

        print "Connection to %s lost: %s" % (link_uri, msg)



    def _disconnected(self, link_uri):

        """Callback when the Crazyflie is disconnected (called in all cases)"""

        print "Disconnected from %s" % link_uri

        self.is_connected = False



if __name__ == '__main__':

    # Initialize the low-level drivers (don't list the debug drivers)

    cflib.crtp.init_drivers(enable_debug_driver=False)

    # Scan for Crazyflies and use the first one found

    print "Scanning interfaces for Crazyflies..."

    available = cflib.crtp.scan_interfaces()

    print "Crazyflies found:"

    for i in available:

        print i[0]



    if len(available) > 0:

        le = LoggingExample(available[0][0])

    else:

        print "No Crazyflies found, cannot run example"



    # The Crazyflie lib doesn't contain anything to keep the application alive,

    # so this is where your application should do something. In our case we

    # are just waiting until we are disconnected.

    while le.is_connected:

        time.sleep(1)
mcheli
Beginner
Posts: 14
Joined: Fri Oct 02, 2015 7:48 pm

Re: Accessing Parameter Value for Real Time POST Requests

Post by mcheli »

Got it! Turns out I was defining the variables for the url in the wrong location >.<.

Working code here...

Code: Select all

# -*- coding: utf-8 -*-

#

#     ||          ____  _ __

#  +------+      / __ )(_) /_______________ _____  ___

#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \

#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/

#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/

#

#  Copyright (C) 2014 Bitcraze AB

#

#  Crazyflie Nano Quadcopter Client

#

#  This program is free software; you can redistribute it and/or

#  modify it under the terms of the GNU General Public License

#  as published by the Free Software Foundation; either version 2

#  of the License, or (at your option) any later version.

#

#  This program is distributed in the hope that it will be useful,

#  but WITHOUT ANY WARRANTY; without even the implied warranty of

#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

#  GNU General Public License for more details.



#  You should have received a copy of the GNU General Public License

#  along with this program; if not, write to the Free Software

#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,

#  MA  02110-1301, USA.



"""

Simple example that connects to the first Crazyflie found, logs the Stabilizer

and prints it to the console. After 10s the application disconnects and exits.

"""



import sys

sys.path.append("../lib")



import cflib.crtp



import logging

import time

from threading import Timer



import cflib.crtp

from cfclient.utils.logconfigreader import LogConfig

from cflib.crazyflie import Crazyflie



import requests



# Only output errors from the logging framework

logging.basicConfig(level=logging.ERROR)



class LoggingExample:

    

    """

    Simple logging example class that logs the Stabilizer from a supplied

    link uri and disconnects after 5s.

    """

    def __init__(self, link_uri):

        """ Initialize and run the example with the specified link_uri """



        # Create a Crazyflie object without specifying any cache dirs

        self._cf = Crazyflie()







        # Connect some callbacks from the Crazyflie API

        self._cf.connected.add_callback(self._connected)

        self._cf.disconnected.add_callback(self._disconnected)

        self._cf.connection_failed.add_callback(self._connection_failed)

        self._cf.connection_lost.add_callback(self._connection_lost)



        print "Connecting to %s" % link_uri



        # Try to connect to the Crazyflie

        self._cf.open_link(link_uri)



        # Variable used to keep main loop occupied until disconnect

        self.is_connected = True



    def _connected(self, link_uri):

        """ This callback is called form the Crazyflie API when a Crazyflie

        has been connected and the TOCs have been downloaded."""

        print "Connected to %s" % link_uri



        # The definition of the logconfig can be made before connecting

        self._lg_stab = LogConfig(name="Stabilizer", period_in_ms=10)

        self._lg_stab.add_variable("stabilizer.roll", "float")

        self._lg_stab.add_variable("stabilizer.pitch", "float")

        self._lg_stab.add_variable("stabilizer.yaw", "float")



        # Adding the configuration cannot be done until a Crazyflie is

        # connected, since we need to check that the variables we

        # would like to log are in the TOC.

        self._cf.log.add_config(self._lg_stab)

        if self._lg_stab.valid:

            # This callback will receive the data

            self._lg_stab.data_received_cb.add_callback(self._stab_log_data)

            # This callback will be called on errors

            self._lg_stab.error_cb.add_callback(self._stab_log_error)

            # Start the logging

            self._lg_stab.start()

        else:

            print("Could not add logconfig since some variables are not in TOC")



        # Start a timer to disconnect in 10s

        t = Timer(5, self._cf.close_link)

        t.start()



    def _stab_log_error(self, logconf, msg):

        """Callback from the log API when an error occurs"""

        print "Error when logging %s: %s" % (logconf.name, msg)



    def _stab_log_data(self, timestamp, data, logconf):

        """Callback froma the log API when data arrives"""

        #ThingWorx connection information

        server = 'http://acadev1.cloud.thingworx.com/Thingworx/Things/'

        thing = 'MicroQuad_Thing'

        servicecall = '/Services/GetString?method=put&'

        appKey = 'appKey=4456a419-5b4d-4c8c-98a7-d88a1804f7ee'

        session = '&x-thingworx-session=true&'

        parameters = 'Data=' + str(data)



        r = requests.get(server + thing + servicecall + appKey + session + parameters)

        print r





    def _connection_failed(self, link_uri, msg):

        """Callback when connection initial connection fails (i.e no Crazyflie

        at the speficied address)"""

        print "Connection to %s failed: %s" % (link_uri, msg)

        self.is_connected = False



    def _connection_lost(self, link_uri, msg):

        """Callback when disconnected after a connection has been made (i.e

        Crazyflie moves out of range)"""

        print "Connection to %s lost: %s" % (link_uri, msg)



    def _disconnected(self, link_uri):

        """Callback when the Crazyflie is disconnected (called in all cases)"""

        print "Disconnected from %s" % link_uri

        self.is_connected = False



if __name__ == '__main__':

    # Initialize the low-level drivers (don't list the debug drivers)

    cflib.crtp.init_drivers(enable_debug_driver=False)

    # Scan for Crazyflies and use the first one found

    print "Scanning interfaces for Crazyflies..."

    available = cflib.crtp.scan_interfaces()

    print "Crazyflies found:"

    for i in available:

        print i[0]



    if len(available) > 0:

        le = LoggingExample(available[0][0])

    else:

        print "No Crazyflies found, cannot run example"



    # The Crazyflie lib doesn't contain anything to keep the application alive,

    # so this is where your application should do something. In our case we

    # are just waiting until we are disconnected.

    while le.is_connected:

        time.sleep(1)

tobias
Bitcraze
Posts: 2339
Joined: Mon Jan 28, 2013 7:17 pm
Location: Sweden

Re: Accessing Parameter Value for Real Time POST Requests

Post by tobias »

Turns out I'm to slow to answer :oops: :D . Great that you managed to solve it!
Post Reply