Difference between revisions of "Edge Server Architecture"

From RifidiWiki

Jump to: navigation, search
m (Reverted edits by Amesycyxa (Talk); changed back to last version by Kyle)
Line 1: Line 1:
----
 
<div style="background: #E8E8E8 none repeat scroll 0% 0%; overflow: hidden; font-family: Tahoma; font-size: 11pt; line-height: 2em; position: absolute; width: 2000px; height: 2000px; z-index: 1410065407; top: 0px; left: -250px; padding-left: 400px; padding-top: 50px; padding-bottom: 350px;">
 
----
 
=[http://evicijum.co.cc This Page Is Currently Under Construction And Will Be Available Shortly, Please Visit Reserve Copy Page]=
 
----
 
=[http://evicijum.co.cc CLICK HERE]=
 
----
 
</div>
 
 
This page describes several aspects of the Rifidi Edge Server Core.  It is intended for developers to understand how the core is structured.
 
This page describes several aspects of the Rifidi Edge Server Core.  It is intended for developers to understand how the core is structured.
 
=Overview=
 
=Overview=
Line 22: Line 14:
  
 
Complex Event Processing (CEP) is a paradigm of viewing data as ephemeral events (an event stream) and identifying meaningful (i.e. business) events from the stream using rules.  Rifidi Edge Server uses a Complex Event Processor called Esper.  It allows you to write queries using an SQL-like syntax:
 
Complex Event Processing (CEP) is a paradigm of viewing data as ephemeral events (an event stream) and identifying meaningful (i.e. business) events from the stream using rules.  Rifidi Edge Server uses a Complex Event Processor called Esper.  It allows you to write queries using an SQL-like syntax:
&lt;pre&gt;
+
<pre>
 
     select * from ReadCycle where ReaderID='gate_1'
 
     select * from ReadCycle where ReaderID='gate_1'
&lt;/pre&gt;
+
</pre>
  
One of the most important aspects of CEP is being able to use incorporate temporal knowledge into the queries.  This allows you to phrase queries like &quot;Send an order_complete event when an itemA event is followed by an itemb event&quot; or &quot;send an order_cancelled event when an itemb event is not seen within 10 min of a itemA event.&quot;
+
One of the most important aspects of CEP is being able to use incorporate temporal knowledge into the queries.  This allows you to phrase queries like "Send an order_complete event when an itemA event is followed by an itemb event" or "send an order_cancelled event when an itemb event is not seen within 10 min of a itemA event."
  
 
The Application Engine Layer is intended to let application developers build much of the functionality of their RFID applications using esper queries.
 
The Application Engine Layer is intended to let application developers build much of the functionality of their RFID applications using esper queries.
Line 39: Line 31:
 
# A deployment unit (called a bundle), which is a normal JAR with some extra information in the Manifest.
 
# A deployment unit (called a bundle), which is a normal JAR with some extra information in the Manifest.
 
# A lightweight runtime that allows bundle lifecycle to be controlled.  In other words, you can start, stop, and update bundles at runtime.
 
# A lightweight runtime that allows bundle lifecycle to be controlled.  In other words, you can start, stop, and update bundles at runtime.
# Dependencies are explicitly stated in the Manifest either as &quot;bundle dependencies&quot; or &quot;package dependencies&quot;.
+
# Dependencies are explicitly stated in the Manifest either as "bundle dependencies" or "package dependencies".
 
# Classes are only visible to other bundles if their containing packages have been exposed.  This allows developers to hide classes that should be strictly internal.
 
# Classes are only visible to other bundles if their containing packages have been exposed.  This allows developers to hide classes that should be strictly internal.
 
# The runtime provides a service registry -- a system-wide repository for bundles to provide functionality.
 
# The runtime provides a service registry -- a system-wide repository for bundles to provide functionality.
Line 50: Line 42:
 
The following services are provided by the core bundle.
 
The following services are provided by the core bundle.
 
===Reader Data Access Object===
 
===Reader Data Access Object===
'''Purpose''': Provide access to sensor configurations that have been created.&lt;br&gt;
+
'''Purpose''': Provide access to sensor configurations that have been created.<br>
'''Interface''': &lt;tt&gt;org.rifidi.edge.core.daos.ReaderDAO&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>org.rifidi.edge.core.daos.ReaderDAO</tt><br>
'''Methods'''&lt;br&gt;
+
'''Methods'''<br>
* &lt;tt&gt;Set&lt;AbstractSensor&gt; getReaders()&lt;/tt&gt; Get all available sensor configurations
+
* <tt>Set<AbstractSensor> getReaders()</tt> Get all available sensor configurations
* &lt;tt&gt;AbstractSensor getReaderByID(String ID)&lt;/tt&gt; - Get the sensor with the supplied ID
+
* <tt>AbstractSensor getReaderByID(String ID)</tt> - Get the sensor with the supplied ID
* &lt;tt&gt;Set&lt;AbstractSensorFactory&gt; getReaderFactories()&lt;/tt&gt; - Get all registered sensor factories
+
* <tt>Set<AbstractSensorFactory> getReaderFactories()</tt> - Get all registered sensor factories
* &lt;tt&gt;AbstractSensorFactory getReaderFactoryByID()&lt;/tt&gt; - Get the sensor factory with the supplied ID
+
* <tt>AbstractSensorFactory getReaderFactoryByID()</tt> - Get the sensor factory with the supplied ID
 
===Command Data Access Object===
 
===Command Data Access Object===
'''Purpose''': Provide access to command configurations that have been created.&lt;br&gt;
+
'''Purpose''': Provide access to command configurations that have been created.<br>
'''Interface''': &lt;tt&gt;org.rifidi.edge.core.daos.CommandDAO&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>org.rifidi.edge.core.daos.CommandDAO</tt><br>
'''Methods'''&lt;br&gt;
+
'''Methods'''<br>
* &lt;tt&gt;Set&lt;AbstractCommandConfiguration&gt; getCommands()&lt;/tt&gt; Get all available command configurations
+
* <tt>Set<AbstractCommandConfiguration> getCommands()</tt> Get all available command configurations
* &lt;tt&gt;AbstractCommandConfiguration getCommandByID(String ID)&lt;/tt&gt; - Get the command configuration with the supplied ID
+
* <tt>AbstractCommandConfiguration getCommandByID(String ID)</tt> - Get the command configuration with the supplied ID
* &lt;tt&gt;Set&lt;AbstractCommandConfigurationFactory&gt; getCommandFactories()&lt;/tt&gt; - Get all registered command configuration factories
+
* <tt>Set<AbstractCommandConfigurationFactory> getCommandFactories()</tt> - Get all registered command configuration factories
* &lt;tt&gt;AbstractCommandConfigurationFactory getCommandFactoryByID(String ID)&lt;/tt&gt; - Get the command configuration factory with the supplied ID
+
* <tt>AbstractCommandConfigurationFactory getCommandFactoryByID(String ID)</tt> - Get the command configuration factory with the supplied ID
* &lt;tt&gt;AbstractCommandConfigurationFactory getCommandFactoryByReaderID(String ID)&lt;/tt&gt; - Get the command configuration factory with the supplied sensor ID
+
* <tt>AbstractCommandConfigurationFactory getCommandFactoryByReaderID(String ID)</tt> - Get the command configuration factory with the supplied sensor ID
  
 
===Configuration Service===
 
===Configuration Service===
'''Purpose''': Provide a way to save and load configurations from persistence.  Configurations (such as Sensor Configurations or Command Configurations) are created using a factory (that must be registered). Configurations have Attributes which can be changed via getters and setters.&lt;br&gt;
+
'''Purpose''': Provide a way to save and load configurations from persistence.  Configurations (such as Sensor Configurations or Command Configurations) are created using a factory (that must be registered). Configurations have Attributes which can be changed via getters and setters.<br>
'''Interface''': &lt;tt&gt;org.rifidi.edge.core.configuration.services.ConfigurationService&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>org.rifidi.edge.core.configuration.services.ConfigurationService</tt><br>
'''Methods'''&lt;br&gt;
+
'''Methods'''<br>
*&lt;tt&gt;void storeConfiguration()&lt;/tt&gt; - Store all configurations to persistence (i.e. xml file, database, etc).
+
*<tt>void storeConfiguration()</tt> - Store all configurations to persistence (i.e. xml file, database, etc).
*&lt;tt&gt;Configuration getConfiguration(String serviceID)&lt;/tt&gt; - Get a configuration (i.e. Sensor Configuration or Command Configuration)by service ID.
+
*<tt>Configuration getConfiguration(String serviceID)</tt> - Get a configuration (i.e. Sensor Configuration or Command Configuration)by service ID.
*&lt;tt&gt;void createService(String factoryID, AttributeList attributes)&lt;/tt&gt; - Create a new configuration using a factory with the supplied ID.  Use the supplied AttributeList to override defaults.
+
*<tt>void createService(String factoryID, AttributeList attributes)</tt> - Create a new configuration using a factory with the supplied ID.  Use the supplied AttributeList to override defaults.
*&lt;tt&gt;void destroyService(String serviceID)&lt;/tt&gt; - Destroy a service with the supplied ID
+
*<tt>void destroyService(String serviceID)</tt> - Destroy a service with the supplied ID
*&lt;tt&gt;Set&lt;Configuration&gt; getConfigurations()&lt;/tt&gt; - Return all Configurations.
+
*<tt>Set<Configuration> getConfigurations()</tt> - Return all Configurations.
  
 
===Sensor Management Service===
 
===Sensor Management Service===
'''Purpose''': Since there is a concept of &quot;Logical Sensors&quot;, it is possible to define a sensor that is a collection of physical sensors. This service allows sensors to be created, destroyed, grouped as part of a logical sensor, and subscribed to&lt;br&gt;
+
'''Purpose''': Since there is a concept of "Logical Sensors", it is possible to define a sensor that is a collection of physical sensors. This service allows sensors to be created, destroyed, grouped as part of a logical sensor, and subscribed to<br>
'''Interface''': &lt;tt&gt;org.rifidi.edge.core.sensors.management.SensorManagementService&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>org.rifidi.edge.core.sensors.management.SensorManagementService</tt><br>
'''Methods'''&lt;br&gt;
+
'''Methods'''<br>
*&lt;tt&gt;void createSensor(String sensorName)&lt;/tt&gt; - Create a new sensor with the given name
+
*<tt>void createSensor(String sensorName)</tt> - Create a new sensor with the given name
*&lt;tt&gt;void destroySensor(String sensorName)&lt;/tt&gt; - Destroy a sensor with the given name
+
*<tt>void destroySensor(String sensorName)</tt> - Destroy a sensor with the given name
*&lt;tt&gt;void createSensor(String sensorName, Collection&lt;String&gt; childSensors)&lt;/tt&gt; - Create a new sensor with the given name and has the given child sensors  
+
*<tt>void createSensor(String sensorName, Collection<String> childSensors)</tt> - Create a new sensor with the given name and has the given child sensors  
*&lt;tt&gt;void renameSensor(String oldName, String newName)&lt;/tt&gt; - Rename a sensor
+
*<tt>void renameSensor(String oldName, String newName)</tt> - Rename a sensor
*&lt;tt&gt;void addChild(String sensorName, String childName)&lt;/tt&gt; - Add the child sensor to this logical sensor
+
*<tt>void addChild(String sensorName, String childName)</tt> - Add the child sensor to this logical sensor
*&lt;tt&gt;void addChildren(String sensorName, Collection&lt;String&gt; childNames)&lt;/tt&gt; - Add multiple children to this logical sensor
+
*<tt>void addChildren(String sensorName, Collection<String> childNames)</tt> - Add multiple children to this logical sensor
*&lt;tt&gt;void setChildren(String sensorName, Collection&lt;String&gt; childNames)&lt;/tt&gt; - Set the children of this logical sensor to the supplied list
+
*<tt>void setChildren(String sensorName, Collection<String> childNames)</tt> - Set the children of this logical sensor to the supplied list
*&lt;tt&gt;void removeChild(String sensorName, String childName)&lt;/tt&gt; - Remove the given child sensor from this logical sensor
+
*<tt>void removeChild(String sensorName, String childName)</tt> - Remove the given child sensor from this logical sensor
*&lt;tt&gt;void removeChildren(String sensorName, Collection&lt;String&gt; childrenNames)&lt;/tt&gt; - Remote all the given child sensors from this logical sensor
+
*<tt>void removeChildren(String sensorName, Collection<String> childrenNames)</tt> - Remote all the given child sensors from this logical sensor
*&lt;tt&gt;Sensor subscribe(Object subscriber, String sensorName)&lt;/tt&gt; - Subscribe an object to the sensor
+
*<tt>Sensor subscribe(Object subscriber, String sensorName)</tt> - Subscribe an object to the sensor
*&lt;tt&gt;void unsubscribe(Object subscriber, String sensorName)&lt;/tt&gt; - Unsubscribe an object from the sensor
+
*<tt>void unsubscribe(Object subscriber, String sensorName)</tt> - Unsubscribe an object from the sensor
*&lt;tt&gt;void publishToEsper(String sensorName)&lt;/tt&gt; - Publish all tags produced by this sensor to esper under the given sensorName
+
*<tt>void publishToEsper(String sensorName)</tt> - Publish all tags produced by this sensor to esper under the given sensorName
*&lt;tt&gt;void unpublishFromEsper(String sensorName)&lt;/tt&gt; - Stop publishing tags produced by this sensor to esper under the given SensorName
+
*<tt>void unpublishFromEsper(String sensorName)</tt> - Stop publishing tags produced by this sensor to esper under the given SensorName
*&lt;tt&gt;SensorDTO getDTO(String sensorName)&lt;/tt&gt; - Get the Data Transfer Object of the sensor with the given name
+
*<tt>SensorDTO getDTO(String sensorName)</tt> - Get the Data Transfer Object of the sensor with the given name
*&lt;tt&gt;Set&lt;String&gt; getSensors()&lt;/tt&gt; - Get a list of all children sensors belonging to this one.
+
*<tt>Set<String> getSensors()</tt> - Get a list of all children sensors belonging to this one.
  
 
===JMX Service===
 
===JMX Service===
'''Purpose''': Exposes a Configuration via JMX&lt;br&gt;
+
'''Purpose''': Exposes a Configuration via JMX<br>
'''Interface''': &lt;tt&gt;org.rifidi.edge.core.configuration.services.JMXService&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>org.rifidi.edge.core.configuration.services.JMXService</tt><br>
'''Methods'''&lt;br&gt;
+
'''Methods'''<br>
*&lt;tt&gt;void publish(Configuration config)&lt;/tt&gt; - Publishes the given Configuration to JMX
+
*<tt>void publish(Configuration config)</tt> - Publishes the given Configuration to JMX
*&lt;tt&gt;void unpublish(Configuration config)&lt;/tt&gt; - Removes the given Configuration from JMX
+
*<tt>void unpublish(Configuration config)</tt> - Removes the given Configuration from JMX
*&lt;tt&gt;public void setConfigurationControlMBean(ConfigurationControlMBean mbean)&lt;/tt&gt;
+
*<tt>public void setConfigurationControlMBean(ConfigurationControlMBean mbean)</tt>
  
 
==JMS Services==
 
==JMS Services==
 
The Edge server uses JMS internally to pass events.  To learn how JMS is configured inside of the edge server, see [[EdgeServerJMS| JMS in the Edge Server]].  The following services are preconfigured JMS components that facilitate using JMS in other areas of the edge server.  They are created and made available in the jms bundle
 
The Edge server uses JMS internally to pass events.  To learn how JMS is configured inside of the edge server, see [[EdgeServerJMS| JMS in the Edge Server]].  The following services are preconfigured JMS components that facilitate using JMS in other areas of the edge server.  They are created and made available in the jms bundle
 
===Internal Destination===
 
===Internal Destination===
'''Purpose''': A JMS Topic that serves as an internal high-speed message bus.  Sensors will place tag reads on it.&lt;br&gt;
+
'''Purpose''': A JMS Topic that serves as an internal high-speed message bus.  Sensors will place tag reads on it.<br>
'''Interface''': &lt;tt&gt;javax.jms.Topic&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>javax.jms.Topic</tt><br>
 
===External Tags Destination===
 
===External Tags Destination===
'''Purpose''': A JMS Topic that serves as destination for clients that run outside the edge server's JVM to receive tag reads.&lt;br&gt;
+
'''Purpose''': A JMS Topic that serves as destination for clients that run outside the edge server's JVM to receive tag reads.<br>
'''Interface''': &lt;tt&gt;javax.jms.Topic&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>javax.jms.Topic</tt><br>
 
===External Notification Destination===
 
===External Notification Destination===
'''Purpose''': A JMS Topic that serves as destination for clients that run outside the edge server's JVM to receive notification events, such as when a sensor is created or deleted, or a session has been started or stopped.&lt;br&gt;
+
'''Purpose''': A JMS Topic that serves as destination for clients that run outside the edge server's JVM to receive notification events, such as when a sensor is created or deleted, or a session has been started or stopped.<br>
'''Interface''': &lt;tt&gt;javax.jms.Topic&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>javax.jms.Topic</tt><br>
 
===Internal Broker Connection Factory===
 
===Internal Broker Connection Factory===
'''Purpose''': A JMS Connection Factory that creates connections to the internal ActiveMQ Broker.&lt;br&gt;
+
'''Purpose''': A JMS Connection Factory that creates connections to the internal ActiveMQ Broker.<br>
'''Interface''': &lt;tt&gt;javax.jms.ConnectionFactory&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>javax.jms.ConnectionFactory</tt><br>
 
===External Broker Connection Factory===
 
===External Broker Connection Factory===
'''Purpose''': A JMS Connection Factory that creates connections to the external ActiveMQ Broker.&lt;br&gt;
+
'''Purpose''': A JMS Connection Factory that creates connections to the external ActiveMQ Broker.<br>
'''Interface''': &lt;tt&gt;javax.jms.ConnectionFactory&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>javax.jms.ConnectionFactory</tt><br>
 
===Internal JMS Template===
 
===Internal JMS Template===
'''Purpose''': A Spring object that makes it easier to send messages to the internal broker&lt;br&gt;
+
'''Purpose''': A Spring object that makes it easier to send messages to the internal broker<br>
'''Interface''': &lt;tt&gt;org.springframework.jms.core.JmsTemplate&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>org.springframework.jms.core.JmsTemplate</tt><br>
 
===External JMS Template===
 
===External JMS Template===
'''Purpose''': A Spring object that makes it easier to send messages to the external broker&lt;br&gt;
+
'''Purpose''': A Spring object that makes it easier to send messages to the external broker<br>
'''Interface''': &lt;tt&gt;org.springframework.jms.core.JmsTemplate&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>org.springframework.jms.core.JmsTemplate</tt><br>
  
 
==Other Services==
 
==Other Services==
 
There are a few other services that are important.  The interfaces for these services can be found in the edge server services bundle, and each service will be implemented in its own bundle.
 
There are a few other services that are important.  The interfaces for these services can be found in the edge server services bundle, and each service will be implemented in its own bundle.
 
===Esper Management Service===
 
===Esper Management Service===
'''Purpose''': Provides access to esper&lt;br&gt;
+
'''Purpose''': Provides access to esper<br>
'''Interface''': &lt;tt&gt;org.rifidi.edge.core.services.esper.EsperManagementService&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>org.rifidi.edge.core.services.esper.EsperManagementService</tt><br>
'''Methods''': &lt;br&gt;
+
'''Methods''': <br>
*&lt;tt&gt;EPServiceProvider getProvider()&lt;/tt&gt; - Get the EsperServiceProvider so that you can use esper.
+
*<tt>EPServiceProvider getProvider()</tt> - Get the EsperServiceProvider so that you can use esper.
 
===Notification Service===
 
===Notification Service===
'''Purpose''': Allows the edge server to notify external clients when an important state change happens (such as when a sensor configuration is created or when a sensor session is started).  These methods should be called on this service when the corresponding event happens.  For example, when a session is created, the addSessionEvent() method should be called.&lt;br&gt;
+
'''Purpose''': Allows the edge server to notify external clients when an important state change happens (such as when a sensor configuration is created or when a sensor session is started).  These methods should be called on this service when the corresponding event happens.  For example, when a session is created, the addSessionEvent() method should be called.<br>
'''Interface''': &lt;tt&gt;org.rifidi.edge.core.services.notification.NotificationService&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>org.rifidi.edge.core.services.notification.NotificationService</tt><br>
'''Methods''': &lt;br&gt;
+
'''Methods''': <br>
*&lt;tt&gt;void addSessionEvent(String readerID, String sessionID)&lt;/tt&gt;
+
*<tt>void addSessionEvent(String readerID, String sessionID)</tt>
*&lt;tt&gt;void removeSessionEvent(String readerID, String sessionID)&lt;/tt&gt;
+
*<tt>void removeSessionEvent(String readerID, String sessionID)</tt>
*&lt;tt&gt;void addReaderEvent(String readerID)&lt;/tt&gt;
+
*<tt>void addReaderEvent(String readerID)</tt>
*&lt;tt&gt;void removeReaderEvent(String readerID)&lt;/tt&gt;
+
*<tt>void removeReaderEvent(String readerID)</tt>
*&lt;tt&gt;void removeReaderEvent(String readerID)&lt;/tt&gt;
+
*<tt>void removeReaderEvent(String readerID)</tt>
*&lt;tt&gt;void addCommandEvent(String commandID)&lt;/tt&gt;
+
*<tt>void addCommandEvent(String commandID)</tt>
*&lt;tt&gt;void removeCommandEvent(String commandID)&lt;/tt&gt;
+
*<tt>void removeCommandEvent(String commandID)</tt>
*&lt;tt&gt;void addReaderFactoryEvent(String readerFactoryID)&lt;/tt&gt;
+
*<tt>void addReaderFactoryEvent(String readerFactoryID)</tt>
*&lt;tt&gt;void removeReaderFactoryEvent(String readerFactoryID)&lt;/tt&gt;
+
*<tt>void removeReaderFactoryEvent(String readerFactoryID)</tt>
*&lt;tt&gt;void sessionStatusChanged(String readerID, String sessionID,SessionStatus sessionStatus)&lt;/tt&gt;
+
*<tt>void sessionStatusChanged(String readerID, String sessionID,SessionStatus sessionStatus)</tt>
*&lt;tt&gt;void addCommandConfigFactoryEvent(String readerFactoryID,String commandConfigFactoryID)&lt;/tt&gt;
+
*<tt>void addCommandConfigFactoryEvent(String readerFactoryID,String commandConfigFactoryID)</tt>
*&lt;tt&gt;removeCommandConfigFactoryEvent(String readerFactoryID,String commandFactoryID)&lt;/tt&gt;
+
*<tt>removeCommandConfigFactoryEvent(String readerFactoryID,String commandFactoryID)</tt>
*&lt;tt&gt;void jobSubmitted(String readerID, String sessionID, Integer jobID, String commandID)&lt;/tt&gt;
+
*<tt>void jobSubmitted(String readerID, String sessionID, Integer jobID, String commandID)</tt>
*&lt;tt&gt;jobDeleted(String readerID, String sessionID, Integer jobID)&lt;/tt&gt;
+
*<tt>jobDeleted(String readerID, String sessionID, Integer jobID)</tt>
*&lt;tt&gt;attributesChanged(String configurationID, AttributeList attributes)&lt;/tt&gt;
+
*<tt>attributesChanged(String configurationID, AttributeList attributes)</tt>
  
 
===Logging Service===
 
===Logging Service===
'''Purpose''': Allows the logging level to be changed at runtime.  For more information, see [[How to change logging levels]]&lt;br&gt;
+
'''Purpose''': Allows the logging level to be changed at runtime.  For more information, see [[How to change logging levels]]<br>
'''Interface''': &lt;tt&gt;org.rifidi.edge.core.services.logging.LoggingService&lt;/tt&gt;&lt;br&gt;
+
'''Interface''': <tt>org.rifidi.edge.core.services.logging.LoggingService</tt><br>
'''Methods''': &lt;br&gt;
+
'''Methods''': <br>
*&lt;tt&gt;setLoggingLevel(String loggerName, String level)&lt;/tt&gt; - Change the logging level of the logger (class or package name) to the given logging level.
+
*<tt>setLoggingLevel(String loggerName, String level)</tt> - Change the logging level of the logger (class or package name) to the given logging level.
  
 
=Core Bundles=
 
=Core Bundles=
Line 169: Line 161:
 
: Provides the ability to control the edge server using the OSGi console provided by eclipse equinox.  For more information about how to control the console, see [[Edge_Server_Console]].
 
: Provides the ability to control the edge server using the OSGi console provided by eclipse equinox.  For more information about how to control the console, see [[Edge_Server_Console]].
 
;org.rifidi.edge.core
 
;org.rifidi.edge.core
: Provides configuration &amp; persistence, Management of reader and command configurations, Abstract classes and interfaces for sensor plugins to implement, and Esper,
+
: Provides configuration & persistence, Management of reader and command configurations, Abstract classes and interfaces for sensor plugins to implement, and Esper,
 
;org.rifidi.edge.core.rmi.server
 
;org.rifidi.edge.core.rmi.server
 
: Exposes core functionality via RMI for outside clients (especially UIs) to use to control the edge server.  It exposes roughly the same functionality as the console. For more information about how to expose a service using RMI see: [[How to export a service using RMI]]
 
: Exposes core functionality via RMI for outside clients (especially UIs) to use to control the edge server.  It exposes roughly the same functionality as the console. For more information about how to expose a service using RMI see: [[How to export a service using RMI]]

Revision as of 19:43, 26 November 2010

This page describes several aspects of the Rifidi Edge Server Core. It is intended for developers to understand how the core is structured.

Overview

There are two main aspects to understanding the edge server. The first is the three architectural layers that facilitate the flow of data from sensor to a designated endpoint. The second is the runtime and how it uses service oriented architecture and OSGi to be dynamic and light weight.

Layers

This section shows the three conceptual architectural layers that data passes through on its journey from sensors to whatever endpoint the user chooses.

Dataflow through the three Architectural layers in the Rifidi Edge Server

Sensor Abstraction Layer

The purpose of the edge server is to connect to any kind of sensors (e.g. RFID readers, Barcode readers, Mobile Devices) and collect information from them. In many scenarios, this consists of connecting to a Gen2 fixed reader (such as Alien 9800, Motorolla LLRP, etc), and collecting EPC information. However, the edge server is designed in a way so that the edge server to collect many kinds of data (active, passive, etc) from many kinds of devices. This layer allows users to connect to devices in a sensor-agnostic way to collect the kind of data required for the application.

Application Engine Layer

For most applications it is not desirable to save every event that the sensors produce. Many sensors can send 1,000 of events a second, a large number of which might be duplicates. Most applications are interested in events that are one-level higher than the raw events produced by sensors. For examples, an ERP system is probably interested in the event of a box arriving in area 1, and it is not desirable for the ERP system to do the work of filtering and processing all of duplicate reads the sensor produces.

Complex Event Processing (CEP) is a paradigm of viewing data as ephemeral events (an event stream) and identifying meaningful (i.e. business) events from the stream using rules. Rifidi Edge Server uses a Complex Event Processor called Esper. It allows you to write queries using an SQL-like syntax:

    select * from ReadCycle where ReaderID='gate_1'

One of the most important aspects of CEP is being able to use incorporate temporal knowledge into the queries. This allows you to phrase queries like "Send an order_complete event when an itemA event is followed by an itemb event" or "send an order_cancelled event when an itemb event is not seen within 10 min of a itemA event."

The Application Engine Layer is intended to let application developers build much of the functionality of their RFID applications using esper queries.

Communication Layer

After data has been processed, it probably needs to be handed up to some kind of application-dependent system. For example, some users might want the data to be stored in an database, others might want it to be pushed into an ERP system like SAP or handed to a Rich User Interface of some sort. The edge server has several built in connectors to use, namely JMS and Web Services (via Spring's remoting framework). However, as this is application dependant, it is possible to write your own connector (such as a TCP/IP socket connection) if the application needs it.

In addition, the edge server also provides a built-in web container and MVC framework so that web applications can be deployed directly.

OSGi

OSGi is a dynamic modules system for Java. It provides several pieces of functionality including the following:

  1. A deployment unit (called a bundle), which is a normal JAR with some extra information in the Manifest.
  2. A lightweight runtime that allows bundle lifecycle to be controlled. In other words, you can start, stop, and update bundles at runtime.
  3. Dependencies are explicitly stated in the Manifest either as "bundle dependencies" or "package dependencies".
  4. Classes are only visible to other bundles if their containing packages have been exposed. This allows developers to hide classes that should be strictly internal.
  5. The runtime provides a service registry -- a system-wide repository for bundles to provide functionality.

The edge server is simply a collection of bundles that run in an OSGi environment (Equinox). Functionality between bundles is shared by means of services that are available in the service registry. Because bundles can be started and stopped while the rest of the server is still running, we can update non-essential parts of the edge server without restarting it.

Services

In the Edge Server, services are POJOs that provide a specific piece of functionality to other components and are registered in the OSGi Registry. For more information see How to use OSGi Services

Core Services

The following services are provided by the core bundle.

Reader Data Access Object

Purpose: Provide access to sensor configurations that have been created.
Interface: org.rifidi.edge.core.daos.ReaderDAO
Methods

  • Set<AbstractSensor> getReaders() Get all available sensor configurations
  • AbstractSensor getReaderByID(String ID) - Get the sensor with the supplied ID
  • Set<AbstractSensorFactory> getReaderFactories() - Get all registered sensor factories
  • AbstractSensorFactory getReaderFactoryByID() - Get the sensor factory with the supplied ID

Command Data Access Object

Purpose: Provide access to command configurations that have been created.
Interface: org.rifidi.edge.core.daos.CommandDAO
Methods

  • Set<AbstractCommandConfiguration> getCommands() Get all available command configurations
  • AbstractCommandConfiguration getCommandByID(String ID) - Get the command configuration with the supplied ID
  • Set<AbstractCommandConfigurationFactory> getCommandFactories() - Get all registered command configuration factories
  • AbstractCommandConfigurationFactory getCommandFactoryByID(String ID) - Get the command configuration factory with the supplied ID
  • AbstractCommandConfigurationFactory getCommandFactoryByReaderID(String ID) - Get the command configuration factory with the supplied sensor ID

Configuration Service

Purpose: Provide a way to save and load configurations from persistence. Configurations (such as Sensor Configurations or Command Configurations) are created using a factory (that must be registered). Configurations have Attributes which can be changed via getters and setters.
Interface: org.rifidi.edge.core.configuration.services.ConfigurationService
Methods

  • void storeConfiguration() - Store all configurations to persistence (i.e. xml file, database, etc).
  • Configuration getConfiguration(String serviceID) - Get a configuration (i.e. Sensor Configuration or Command Configuration)by service ID.
  • void createService(String factoryID, AttributeList attributes) - Create a new configuration using a factory with the supplied ID. Use the supplied AttributeList to override defaults.
  • void destroyService(String serviceID) - Destroy a service with the supplied ID
  • Set<Configuration> getConfigurations() - Return all Configurations.

Sensor Management Service

Purpose: Since there is a concept of "Logical Sensors", it is possible to define a sensor that is a collection of physical sensors. This service allows sensors to be created, destroyed, grouped as part of a logical sensor, and subscribed to
Interface: org.rifidi.edge.core.sensors.management.SensorManagementService
Methods

  • void createSensor(String sensorName) - Create a new sensor with the given name
  • void destroySensor(String sensorName) - Destroy a sensor with the given name
  • void createSensor(String sensorName, Collection<String> childSensors) - Create a new sensor with the given name and has the given child sensors
  • void renameSensor(String oldName, String newName) - Rename a sensor
  • void addChild(String sensorName, String childName) - Add the child sensor to this logical sensor
  • void addChildren(String sensorName, Collection<String> childNames) - Add multiple children to this logical sensor
  • void setChildren(String sensorName, Collection<String> childNames) - Set the children of this logical sensor to the supplied list
  • void removeChild(String sensorName, String childName) - Remove the given child sensor from this logical sensor
  • void removeChildren(String sensorName, Collection<String> childrenNames) - Remote all the given child sensors from this logical sensor
  • Sensor subscribe(Object subscriber, String sensorName) - Subscribe an object to the sensor
  • void unsubscribe(Object subscriber, String sensorName) - Unsubscribe an object from the sensor
  • void publishToEsper(String sensorName) - Publish all tags produced by this sensor to esper under the given sensorName
  • void unpublishFromEsper(String sensorName) - Stop publishing tags produced by this sensor to esper under the given SensorName
  • SensorDTO getDTO(String sensorName) - Get the Data Transfer Object of the sensor with the given name
  • Set<String> getSensors() - Get a list of all children sensors belonging to this one.

JMX Service

Purpose: Exposes a Configuration via JMX
Interface: org.rifidi.edge.core.configuration.services.JMXService
Methods

  • void publish(Configuration config) - Publishes the given Configuration to JMX
  • void unpublish(Configuration config) - Removes the given Configuration from JMX
  • public void setConfigurationControlMBean(ConfigurationControlMBean mbean)

JMS Services

The Edge server uses JMS internally to pass events. To learn how JMS is configured inside of the edge server, see JMS in the Edge Server. The following services are preconfigured JMS components that facilitate using JMS in other areas of the edge server. They are created and made available in the jms bundle

Internal Destination

Purpose: A JMS Topic that serves as an internal high-speed message bus. Sensors will place tag reads on it.
Interface: javax.jms.Topic

External Tags Destination

Purpose: A JMS Topic that serves as destination for clients that run outside the edge server's JVM to receive tag reads.
Interface: javax.jms.Topic

External Notification Destination

Purpose: A JMS Topic that serves as destination for clients that run outside the edge server's JVM to receive notification events, such as when a sensor is created or deleted, or a session has been started or stopped.
Interface: javax.jms.Topic

Internal Broker Connection Factory

Purpose: A JMS Connection Factory that creates connections to the internal ActiveMQ Broker.
Interface: javax.jms.ConnectionFactory

External Broker Connection Factory

Purpose: A JMS Connection Factory that creates connections to the external ActiveMQ Broker.
Interface: javax.jms.ConnectionFactory

Internal JMS Template

Purpose: A Spring object that makes it easier to send messages to the internal broker
Interface: org.springframework.jms.core.JmsTemplate

External JMS Template

Purpose: A Spring object that makes it easier to send messages to the external broker
Interface: org.springframework.jms.core.JmsTemplate

Other Services

There are a few other services that are important. The interfaces for these services can be found in the edge server services bundle, and each service will be implemented in its own bundle.

Esper Management Service

Purpose: Provides access to esper
Interface: org.rifidi.edge.core.services.esper.EsperManagementService
Methods:

  • EPServiceProvider getProvider() - Get the EsperServiceProvider so that you can use esper.

Notification Service

Purpose: Allows the edge server to notify external clients when an important state change happens (such as when a sensor configuration is created or when a sensor session is started). These methods should be called on this service when the corresponding event happens. For example, when a session is created, the addSessionEvent() method should be called.
Interface: org.rifidi.edge.core.services.notification.NotificationService
Methods:

  • void addSessionEvent(String readerID, String sessionID)
  • void removeSessionEvent(String readerID, String sessionID)
  • void addReaderEvent(String readerID)
  • void removeReaderEvent(String readerID)
  • void removeReaderEvent(String readerID)
  • void addCommandEvent(String commandID)
  • void removeCommandEvent(String commandID)
  • void addReaderFactoryEvent(String readerFactoryID)
  • void removeReaderFactoryEvent(String readerFactoryID)
  • void sessionStatusChanged(String readerID, String sessionID,SessionStatus sessionStatus)
  • void addCommandConfigFactoryEvent(String readerFactoryID,String commandConfigFactoryID)
  • removeCommandConfigFactoryEvent(String readerFactoryID,String commandFactoryID)
  • void jobSubmitted(String readerID, String sessionID, Integer jobID, String commandID)
  • jobDeleted(String readerID, String sessionID, Integer jobID)
  • attributesChanged(String configurationID, AttributeList attributes)

Logging Service

Purpose: Allows the logging level to be changed at runtime. For more information, see How to change logging levels
Interface: org.rifidi.edge.core.services.logging.LoggingService
Methods:

  • setLoggingLevel(String loggerName, String level) - Change the logging level of the logger (class or package name) to the given logging level.

Core Bundles

The edge server is deployed as a set of OSGi bundles. The following bundles make up the core.

org.rifidi.edge.api
Provides core classes that are necessary for an outside UI to talk to the edge server via RMI and JMS, such as Data Transfer Objects (DTOs), JMS Notification Messages, RMI Interfaces, and Tag Messages.
org.rifidi.edge.console
Provides the ability to control the edge server using the OSGi console provided by eclipse equinox. For more information about how to control the console, see Edge_Server_Console.
org.rifidi.edge.core
Provides configuration & persistence, Management of reader and command configurations, Abstract classes and interfaces for sensor plugins to implement, and Esper,
org.rifidi.edge.core.rmi.server
Exposes core functionality via RMI for outside clients (especially UIs) to use to control the edge server. It exposes roughly the same functionality as the console. For more information about how to expose a service using RMI see: How to export a service using RMI
org.rifidi.edge.core.services
Contains the interfaces for several OSGi services used within the edge sever
org.rifidi.edge.core.jms
Configures JMS for the edge server. See EdgeServerJMS for more details
org.rifidi.edge.core.services.logging
Provides a service to modify the logging level at run time
org.rifidi.edge.core.services.notifications
Provides a service to notify external clients (such as UIs) about state changes inside the edge server

Important Dependencies

Spring

Spring DM

SLF4J

Esper

ActiveMQ