<commit_before>= Using Sensors In Seattle =

A Seattle / Repy program cannot access resources like GPS, wifi signal strength information, motion sensors, etc.   However, many users would like to provide information about resources like this to researchers.   To facilitate the exchange of information, we provide an API that sensor applications (installed separately from Seattle) can use to make the sensor available to local Repy programs.

[[TOC(inline)]]

== Overview ==

The API that is provided by sensors may vary significantly from application to application.   The philosophy is to provide an API that is as simple as possible but would allow a variety of sensor applications to operate.   We intentionally under constrain the interface to make it as easy as possible to use in the base case.   Further parts of this document describe how to do slightly more advanced functionality while providing this API.

== Required API ==

All sensors must provide an XMLRPC interface bound to 127.0.0.1 on any port from 63090-63099.   This XMLRPC interface must support at least the following two calls:  {{{isSeattleSensor()}}}, {{{system.listMethods()}}}, and {{{system.methodSignature}}}.   (See [http://docs.python.org/library/simplexmlrpcserver.html the SimpleXMLRPCAPI] for general details on Python, but similar libraries exist on other platforms.)   The {{{isSeattleSensor()}}} call must return True.   The {{{system.listMethods()}}} should list the available calls.   The {{{system.methodSignature(callname)}}} must return the calling arguments for a function.

'''Note: it is completely fine for a sensor to hide calls it does not want to be called by general clients.'''   In other words, if you have a call that performs a potentially disruptive act, you need not list it.   Keep in mind that this is not a security mechanism.   It is just to prevent a simple and general client from calling it without understanding what it does.

It is also '''recommended''' that you provide the call {{{system.methodHelp}}}.   This is not required and clients '''must not''' rely on their existence.

== Example Use ==

Here is some example pseudo-code for building a sensor and client.   

Sensor code:

{{{
import SimpleXMLRPCServer
import socket
import sys

for sensorport in [63095, 63096, 63097, 63098, 63099, 63090, 63091, 63092, 63093, 63094]:
  try:
    server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", sensorport))
    server.register_introspection_functions()
  except socket.error:
    print 'port:',sensorport,'failed.   Trying backup port...' 
    continue
  print "Listening on port",sensorport,"..." 
  break
else:
  print 'Could not locate a port!'
  sys.exit(1)
    
def isSeattleSensor():
  """ isSeattleSensor() always returns True"""
  return True

def mySensorName():
  """ my sensor name is "Hello World Sensor"."""
  return "Hello World Sensor"

def readSensor():
  """ Read data from the hello world sensor"""
  return "Hello World!"

def readSensorForLanguage(language):
  """ Read data from the hello world sensor in a few languages.   Pass in a string."""
  if language == 'English':
    return "Hello World!"
  elif language == 'German':
    return "Hallo Welt!"
  elif language == 'Mandarin':
    return "Ni Hao!"
  else:
    raise Exception("Unsupported language")

# NOTE: the system.* calls are defined by the SimpleXMLRPCServer in Python by calling the following.   Your library's use may vary.
server.register_introspection_functions()

server.register_function(mySensorName)
server.register_function(readSensor)
server.register_function(readSensorForLanguage)
server.register_function(isSeattleSensor)

try:
    print 'Use Control-C to exit'
    server.serve_forever()
except KeyboardInterrupt:
    print 'Exiting'

}}}


Repy sensor reading code:
{{{
include xmlrpc_client.repy

if callfunc=="initialize":
  for sensorport in [63095, 63096, 63097, 63098, 63099, 63090, 
    63091, 63092, 63093, 63094]:
    try:
      s = xmlrpc_client_Client('http://localhost:'+str(sensorport))
    except socket.error:
      print 'port:', sensorport, 'failed.   Trying backup port...' 
      continue
    print "Connected to port", sensorport
    break
  else:
    print 'Could not locate a port!'
    exitall()

  # should check the error status...
  try: 
    if not s.send_request("isSeattleSensor", ()):
      print 'something other than a Seattle sensor was bound to the port...'
      exitall()
  except Exception, e:
    print 'Got an error when checking if this is a Seattle sensor:', str(e)
    exitall()

  # Get the list of available methods
  methodlist = s.send_request("system.listMethods", ())

  for methodname in methodlist:
    # NOTE: Wrap the methodname string inside a tuple, otherwise
    # xmlrpc_common will treat the string's characters as separate params
    thissignature = s.send_request("system.methodSignature", (methodname,))

    # BUG: This is true for all signatures, but shouldn't be.
    if thissignature == 'signatures not supported':
      print 'Method:', methodname, 'has an unknown signature.'
    else:  
      print 'Method:',methodname,'has the signature', thissignature

    if thissignature == ():
      print 'Empty call returns:', s.send_request(methodname, ())

  print s.send_request("isSeattleSensor", ())
  print s.send_request("mySensorName", ())
  print s.send_request("readSensor", ())
  print s.send_request("readSensorForLanguage", ('Mandarin',))

}}}

== Sensors on Android == 

Smartphones often come with a number of embedded sensors and chips, such as an accelerometer, GPS, Wifi card, etc. New sensing applications therefore can turn an everyday phone into a smart sensor. As we have Seattle ported on Android platform ([https://seattle.cs.washington.edu/wiki/SeattleOnAndroid SeattleOnAndroid]), here is a brief introduction how to provide APIs that an Android application can use to make the sensor available to Seattle on Android.

=== XMLRPC Library ===

Python has a set of quick and easy [http://docs.python.org/library/simplexmlrpcserver.html the SimpleXMLRPCAPI] available. However, Android Java applications have to import their own library. [http://ws.apache.org/xmlrpc/ Apache WS-XMLRPC] is one of the most popular Java XMLRPC libraries. Here are a few steps how to import it, and create a light weight SimpleXmlRPcServer for Android. 

==== Importing Apache ====

Download the Apache library from [http://ws.apache.org/xmlrpc/ Apache WS-XMLRPC]. The jar files in /apache-xmlrpc-version-number/lib/ are what you need. Create a new folder ''libs'' in your Eclipse Android project (the libs folder will be automatically created by Eclipse with higher version (>15) of Android API).

Right click libs and choose Import -> General -> File System, then Next. Browse in the filesystem to find the library's parent directory (i.e., /apache-xmlrpc-version-number/lib/). Click the directory name, then check the relevant jar files in the right pane. This puts the library physically into your project. 

Right click on your Android project, choose properties -> "Java Build Path" tab, click the Libraries tab, then "Add JARs...", navigate to the new jar files you just imported in the ''libs'' directory and add it. They should now appear under “Referenced Libraries” in your project. This is the moment when your new jar files are converted for use on Android.

==== SimpleXmlRPcServer for Android ====

[http://www.zugiart.com/2010/09/java-apache-simple-xmlrpc-server/ zen] developed a simple and light weight SimpleXmlRPcServer using the above Apache library, which allows us to very quickly craft a standalone, simple XMLRPC server using the above Apache library. No servlet or container is required. 

Two classes are needed for the server, '''SimpleXmlRPcServer''' and '''SimpleXmlRPcRequestHandlerFactory''' on zen's page. Simply place these two classes in your project then you are ready to go (in case the website goes down in the future, I attached the code below. Remember to replace the first line with your own package name). According to zen, the code "supports single instance handler object, but not yet multi-threaded". 

=== Example Use ===

Here are some example code for building Android sensor (XMLRPC server) and a client. 

Sensor code:
{{{
public class RpcServer extends IntentService {
        private int[] portArray = new int[] {63090, 63091, 63092, 63093, 63094, 63095, 63096, 63097, 63098, 63099};
	private int port = 0;
        .........<commit_msg>Revision 14 of UsingSensors<commit_after>= Using Sensors In Seattle =

A Seattle / Repy program cannot access resources like GPS, wifi signal strength information, motion sensors, etc.   However, many users would like to provide information about resources like this to researchers.   To facilitate the exchange of information, we provide an API that sensor applications (installed separately from Seattle) can use to make the sensor available to local Repy programs.

[[TOC(inline)]]

== Overview ==

The API that is provided by sensors may vary significantly from application to application.   The philosophy is to provide an API that is as simple as possible but would allow a variety of sensor applications to operate.   We intentionally under constrain the interface to make it as easy as possible to use in the base case.   Further parts of this document describe how to do slightly more advanced functionality while providing this API.

== Required API ==

All sensors must provide an XMLRPC interface bound to 127.0.0.1 on any port from 63090-63099.   This XMLRPC interface must support at least the following two calls:  {{{isSeattleSensor()}}}, {{{system.listMethods()}}}, and {{{system.methodSignature}}}.   (See [http://docs.python.org/library/simplexmlrpcserver.html the SimpleXMLRPCAPI] for general details on Python, but similar libraries exist on other platforms.)   The {{{isSeattleSensor()}}} call must return True.   The {{{system.listMethods()}}} should list the available calls.   The {{{system.methodSignature(callname)}}} must return the calling arguments for a function.

'''Note: it is completely fine for a sensor to hide calls it does not want to be called by general clients.'''   In other words, if you have a call that performs a potentially disruptive act, you need not list it.   Keep in mind that this is not a security mechanism.   It is just to prevent a simple and general client from calling it without understanding what it does.

It is also '''recommended''' that you provide the call {{{system.methodHelp}}}.   This is not required and clients '''must not''' rely on their existence.

== Example Use ==

Here is some example pseudo-code for building a sensor and client.   

Sensor code:

{{{
import SimpleXMLRPCServer
import socket
import sys

for sensorport in [63095, 63096, 63097, 63098, 63099, 63090, 63091, 63092, 63093, 63094]:
  try:
    server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", sensorport))
    server.register_introspection_functions()
  except socket.error:
    print 'port:',sensorport,'failed.   Trying backup port...' 
    continue
  print "Listening on port",sensorport,"..." 
  break
else:
  print 'Could not locate a port!'
  sys.exit(1)
    
def isSeattleSensor():
  """ isSeattleSensor() always returns True"""
  return True

def mySensorName():
  """ my sensor name is "Hello World Sensor"."""
  return "Hello World Sensor"

def readSensor():
  """ Read data from the hello world sensor"""
  return "Hello World!"

def readSensorForLanguage(language):
  """ Read data from the hello world sensor in a few languages.   Pass in a string."""
  if language == 'English':
    return "Hello World!"
  elif language == 'German':
    return "Hallo Welt!"
  elif language == 'Mandarin':
    return "Ni Hao!"
  else:
    raise Exception("Unsupported language")

# NOTE: the system.* calls are defined by the SimpleXMLRPCServer in Python by calling the following.   Your library's use may vary.
server.register_introspection_functions()

server.register_function(mySensorName)
server.register_function(readSensor)
server.register_function(readSensorForLanguage)
server.register_function(isSeattleSensor)

try:
    print 'Use Control-C to exit'
    server.serve_forever()
except KeyboardInterrupt:
    print 'Exiting'

}}}


Repy sensor reading code:
{{{
include xmlrpc_client.repy

if callfunc=="initialize":
  for sensorport in [63095, 63096, 63097, 63098, 63099, 63090, 
    63091, 63092, 63093, 63094]:
    try:
      s = xmlrpc_client_Client('http://localhost:'+str(sensorport))
    except socket.error:
      print 'port:', sensorport, 'failed.   Trying backup port...' 
      continue
    print "Connected to port", sensorport
    break
  else:
    print 'Could not locate a port!'
    exitall()

  # should check the error status...
  try: 
    if not s.send_request("isSeattleSensor", ()):
      print 'something other than a Seattle sensor was bound to the port...'
      exitall()
  except Exception, e:
    print 'Got an error when checking if this is a Seattle sensor:', str(e)
    exitall()

  # Get the list of available methods
  methodlist = s.send_request("system.listMethods", ())

  for methodname in methodlist:
    # NOTE: Wrap the methodname string inside a tuple, otherwise
    # xmlrpc_common will treat the string's characters as separate params
    thissignature = s.send_request("system.methodSignature", (methodname,))

    # BUG: This is true for all signatures, but shouldn't be.
    if thissignature == 'signatures not supported':
      print 'Method:', methodname, 'has an unknown signature.'
    else:  
      print 'Method:',methodname,'has the signature', thissignature

    if thissignature == ():
      print 'Empty call returns:', s.send_request(methodname, ())

  print s.send_request("isSeattleSensor", ())
  print s.send_request("mySensorName", ())
  print s.send_request("readSensor", ())
  print s.send_request("readSensorForLanguage", ('Mandarin',))

}}}

== Sensors on Android == 

Smartphones often come with a number of embedded sensors and chips, such as an accelerometer, GPS, Wifi card, etc. New sensing applications therefore can turn an everyday phone into a smart sensor. As we have Seattle ported on Android platform ([https://seattle.poly.edu/wiki/SeattleOnAndroid SeattleOnAndroid]), here is a brief introduction how to provide APIs that an Android application can use to make the sensor available to Seattle on Android.

=== XMLRPC Library ===

Python has a set of quick and easy [http://docs.python.org/library/simplexmlrpcserver.html the SimpleXMLRPCAPI] available. However, Android Java applications have to import their own library. [http://ws.apache.org/xmlrpc/ Apache WS-XMLRPC] is one of the most popular Java XMLRPC libraries. Here are a few steps how to import it, and create a light weight SimpleXmlRPcServer for Android. 

==== Importing Apache ====

Download the Apache library from [http://ws.apache.org/xmlrpc/ Apache WS-XMLRPC]. The jar files in /apache-xmlrpc-version-number/lib/ are what you need. Create a new folder ''libs'' in your Eclipse Android project (the libs folder will be automatically created by Eclipse with higher version (>15) of Android API).

Right click libs and choose Import -> General -> File System, then Next. Browse in the filesystem to find the library's parent directory (i.e., /apache-xmlrpc-version-number/lib/). Click the directory name, then check the relevant jar files in the right pane. This puts the library physically into your project. 

Right click on your Android project, choose properties -> "Java Build Path" tab, click the Libraries tab, then "Add JARs...", navigate to the new jar files you just imported in the ''libs'' directory and add it. They should now appear under “Referenced Libraries” in your project. This is the moment when your new jar files are converted for use on Android.

==== SimpleXmlRPcServer for Android ====

[http://www.zugiart.com/2010/09/java-apache-simple-xmlrpc-server/ zen] developed a simple and light weight SimpleXmlRPcServer using the above Apache library, which allows us to very quickly craft a standalone, simple XMLRPC server using the above Apache library. No servlet or container is required. 

Two classes are needed for the server, '''SimpleXmlRPcServer''' and '''SimpleXmlRPcRequestHandlerFactory''' on zen's page. Simply place these two classes in your project then you are ready to go (in case the website goes down in the future, I attached the code below. Remember to replace the first line with your own package name). According to zen, the code "supports single instance handler object, but not yet multi-threaded". 

=== Example Use ===

Here are some example code for building Android sensor (XMLRPC server) and a client. 

Sensor code:
{{{
public class RpcServer extends IntentService {
        private int[] portArray = new int[] {63090, 63091, 63092, 63093, 63094, 63095, 63096, 63097, 63098, 63099};
	private int port = 0;
        .........
{'fraction_non_alphanumeric': 0.08804623459338326, 'fraction_numerical': 0.020876334257238897, 'mean_word_length': 4.213034122348601, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 20}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1826971', 'n_tokens_mistral': 4760, 'n_tokens_neox': 4426, 'n_words': 2107}