2jciebu01: put new sources in right location

Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
This commit is contained in:
Mihai Tudor Panu
2019-04-04 16:52:01 -07:00
parent e0be90589b
commit b08eef0197
16 changed files with 2710 additions and 2714 deletions

View File

@ -0,0 +1,500 @@
/*
* Author: Hiroyuki Mino <omronsupportupm@omron.com>
* Copyright (c) 2019 Omron Electronic Components - Americas
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "2jciebu01_ble.hpp"
using namespace upm;
using namespace std;
OM2JCIEBU_BLE::OM2JCIEBU_BLE(std::string ble_address)
{
//initializing tinyB
try {
bleManager = BluetoothManager::get_bluetooth_manager();
} catch(const std::runtime_error& e) {
std::cerr << "Error while initializing libtinyb: " << e.what() << std::endl;
exit(1);
}
OM2JCIEBU_BLE::bleMACaddress = ble_address;
}
bool OM2JCIEBU_BLE::connectBleDevice(std::string ble_address)
{
bool ret;
//Start BLE discovery
if(startBleDiscovery()) {
std::cout << "Searching for Sensor...\r\n";
for(int i = 0; i < OM2JCIEBU_BLE_DISCOVERY_RETRY ; ++i) {
auto list = bleManager->get_devices();
for(auto it = list.begin(); it != list.end(); ++it) {
#if DEBUG_LOG
std::cout << "Class = " << (*it)->get_class_name() << " ";
std::cout << "Path = " << (*it)->get_object_path() << " ";
std::cout << "Name = " << (*it)->get_name() << " ";
std::cout << "Connected = " << (*it)->get_connected() << " ";
std::cout << std::endl;
#endif
/* Search for the device with the address given as a parameter to the program */
if((*it)->get_address() == ble_address) {
bleSensorTag = (*it).release();
}
}
/* Free the list of devices and stop if the device was found */
if(bleSensorTag != nullptr) {
std::cout << "Omron Sensor found : " << ble_address << std::endl;
break;
}
std::this_thread::sleep_for(std::chrono::seconds(4));
}
}
ret = stopBleDiscovery();
std::cout << "Stopped Ble Discovery = " << (ret ? "true" : "false") << std::endl;
if(bleSensorTag == nullptr) {
throw std::runtime_error(std::string(__FUNCTION__) +
": Could not find device " + ble_address);
}
if(bleSensorTag->connect()) {
is_BleConnected = true;
}
return is_BleConnected;
}
bool OM2JCIEBU_BLE::removeBleDevice()
{
if(is_BleConnected) { //disconnect with device if connected
if(bleSensorTag->disconnect()) {
is_BleConnected = false;
}
}
return is_BleConnected;
}
bool OM2JCIEBU_BLE::startBleDiscovery()
{
return bleManager->start_discovery();
}
bool OM2JCIEBU_BLE::stopBleDiscovery()
{
return bleManager->stop_discovery();
}
bool OM2JCIEBU_BLE::writePacket(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name, const std::vector<unsigned char> &arg_value)
{
if(!(is_BleConnected)) { //Connect with device if not connected
if(!(connectBleDevice(OM2JCIEBU_BLE::bleMACaddress))) {
return false;
}
}
const char *cptr = (const char *)malloc(MAX_UUID_SIZE);
if(cptr == NULL) {
printf("Error. Allocation was unsuccessful. \r\n");
return false;
}
memset((void *)cptr, 0, 64);
getAddress(attribute_name, BLE, (void *)cptr);
std::string uuid = ((const char *)cptr);
free((void *)cptr);
uint16_t getServiceRetryCount = 0;
while(true) {
auto list = bleSensorTag->get_services();
//check for service list is empty or not
if(list.empty()) {
std::cout << "get services list empty " << std::endl;
getServiceRetryCount++;
if(getServiceRetryCount == OM2JCIEBU_BLE_DISCOVERY_RETRY) {
getServiceRetryCount = 0;
removeBleDevice();
throw std::runtime_error(std::string(__FUNCTION__) +
": Could not find services ");
}
sleep(1);
continue;
}
for(auto it = list.begin(); it != list.end(); ++it) {
#if DEBUG_LOG
std::cout << "Class = " << (*it)->get_class_name() << " ";
std::cout << "Path = " << (*it)->get_object_path() << " ";
std::cout << "UUID = " << (*it)->get_uuid() << " ";
std::cout << "Device = " << (*it)->get_device().get_object_path() << " ";
std::cout << std::endl;
#endif
/* Search for the LIVE sensor data service, by UUID */
if((*it)->get_uuid() == OM2JCIEBU_BLE_LED_AND_ADV_CONFIGUARTION_SERVICE) {
bleService = (*it).release();
}
}
break;
}
if(bleService != nullptr) {
auto charList = bleService->get_characteristics();
std::cout << "Discovered characteristics: " << uuid << std::endl;
for(auto it = charList.begin(); it != charList.end(); ++it) {
#if DEBUG_LOG
std::cout << "Class = " << (*it)->get_class_name() << " ";
std::cout << "Path = " << (*it)->get_object_path() << " ";
std::cout << "UUID = " << (*it)->get_uuid() << " ";
std::cout << "Service = " << (*it)->get_service().get_object_path() << " ";
std::cout << std::endl;
#endif
if((*it)->get_uuid() == uuid) {
bleSensorChar = (*it).release();
}
}
} else {
//If not find any sevice then disconnect BLE device
removeBleDevice();
throw std::runtime_error(std::string(__FUNCTION__) +
": Could not find Service ");
}
if(bleSensorChar == nullptr) {
//If not find any characteristics then disconnect BLE device
removeBleDevice();
throw std::runtime_error(std::string(__FUNCTION__) +
": Could not find characteristics ");
}
bool ret = bleSensorChar->write_value(arg_value, 0);
return ret;
}
OM2JCIEBU_BLE::OM2JCIEBU_ERROR_T OM2JCIEBU_BLE::getDiscoveredServices(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name)
{
if(!(is_BleConnected)) { //Connect with device if not connected
if(!(connectBleDevice(OM2JCIEBU_BLE::bleMACaddress))) {
return FAILURE;
}
}
short int getServiceRetryCount = 0;
const char *cptr = (const char *)malloc(MAX_UUID_SIZE);
if(cptr == NULL) {
printf("Error. Allocation was unsuccessful. \r\n");
return FAILURE;
}
memset((void *)cptr, 0, MAX_UUID_SIZE);
getAddress(attribute_name, BLE, (void *)cptr);
std::string uuid = ((const char *)cptr);
free((void *)cptr);
//read services from connected BLE device
while(true) {
auto list = bleSensorTag->get_services();
if(list.empty()) {
std::cout << "get services list empty " << std::endl;
getServiceRetryCount++;
if(getServiceRetryCount == OM2JCIEBU_BLE_DISCOVERY_RETRY) {
getServiceRetryCount = 0;
removeBleDevice();
throw std::runtime_error(std::string(__FUNCTION__) +
": Not Found any service ");
}
sleep(1);
continue;
}
for(auto it = list.begin(); it != list.end(); ++it) {
#if DEBUG_LOG
std::cout << "Class = " << (*it)->get_class_name() << " ";
std::cout << "Path = " << (*it)->get_object_path() << " ";
std::cout << "UUID = " << (*it)->get_uuid() << " ";
std::cout << "Device = " << (*it)->get_device().get_object_path() << " ";
std::cout << std::endl;
#endif
//check for service
if((*it)->get_uuid() == OM2JCIEBU_BLE_LIVE_SENSOR_DATA_SERVICE) {
bleService = (*it).release();
}
}
break;
}
if(bleService != nullptr) {
auto charList = bleService->get_characteristics();
std::cout << "Discovered characteristics: " << uuid << std::endl;
for(auto it = charList.begin(); it != charList.end(); ++it) {
#if DEBUG_LOG
std::cout << "Class = " << (*it)->get_class_name() << " ";
std::cout << "Path = " << (*it)->get_object_path() << " ";
std::cout << "UUID = " << (*it)->get_uuid() << " ";
std::cout << "Service = " << (*it)->get_service().get_object_path() << " ";
std::cout << std::endl;
#endif
//compare UUID
if((*it)->get_uuid() == uuid) {
bleSensorChar = (*it).release();
return SUCCESS;
}
}
} else {
//If not find any sevice then disconnect BLE device
removeBleDevice();
throw std::runtime_error(std::string(__FUNCTION__) +
": Could not find characteristics ");
}
if(bleSensorChar == nullptr) {
//If not find any characteristics then disconnect BLE device
removeBleDevice();
throw std::runtime_error(std::string(__FUNCTION__) +
": Could not find characteristics ");
}
return FAILURE;
}
OM2JCIEBU_BLE::OM2JCIEBU_ERROR_T OM2JCIEBU_BLE::getSensorData(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name, void *attribute_data)
{
if(attribute_data == NULL) {
std::cout << "Null pointer received..." << std::endl;
return FAILURE;
}
unsigned char *data;
OM2JCIEBU_BLE::OM2JCIEBU_ERROR_T verifyResult = FAILURE;
//Read raw data from connected BLE device based on characteristics
std::vector<unsigned char> response = bleSensorChar->read_value();
unsigned int size = response.size();
if(size > 0) {
data = response.data();
#if DEBUG_LOG
std::cout << "Raw data=[";
for(unsigned i = 0; i < response.size(); i++)
std::cout << std::hex << static_cast<int>(data[i]) << ", ";
std::cout << "] ";
std::cout << "" << std::endl;
#endif
//parse a data which is read from connected device
parseSensorData(data);
//Get data from structer
getSensorAttribute(attribute_name, attribute_data);
verifyResult = SUCCESS;
}
return verifyResult;
}
OM2JCIEBU_BLE::OM2JCIEBU_ERROR_T OM2JCIEBU_BLE::getAdvSensorData(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name, void *attribute_data)
{
if(attribute_data == NULL) {
std::cout << "Null pointer received..." << std::endl;
return FAILURE;
}
uint8_t advSensordata[MAX_SENSOR_DATA_SIZE] = {0};
int advDataindex = 0;
OM2JCIEBU_BLE::OM2JCIEBU_ERROR_T verifyResult = FAILURE;
if(is_BleConnected) { //disconnect with device if connected
removeBleDevice();
is_BleConnected = false;
}
if(startBleDiscovery()) {
auto list = bleManager->get_devices();
for(auto it = list.begin(); it != list.end(); ++it) {
//read manufacturer data
auto mfg = (*it)->get_manufacturer_data();
if(!mfg.empty()) {
//read manufacturer data for particular MAC address which is given by user
if((*it)->get_address() == bleMACaddress) {
#if DEBUG_LOG
std::cout << "MFG" << std::endl;
for(auto it : mfg) {
std::cout << it.second.size() << std::endl;
std::cout << "\t" << it.first << " = [ ";
for(auto arr_it : it.second) {
std::cout << std::hex << (int) arr_it << ", ";
}
std::cout << "]" << std::endl;
}
#endif
//store in buffer for verify data and parsing
for(auto it : mfg) {
advSensordata[advDataindex++] = it.first;
advSensordata[advDataindex++] = it.first >> 8;
for(auto arr_it : it.second) {
advSensordata[advDataindex++] = arr_it;
}
}
//verfiy a packet
verifyResult = verifyPacket(advSensordata, advDataindex);
if(verifyResult == SUCCESS) {
parseAdvSensorData(advSensordata);
getSensorAttribute(attribute_name, attribute_data);
advDataindex = 0;
}
}
}
}
}
return verifyResult;
}
void OM2JCIEBU_BLE::getSensorAttribute(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name, void *attributeValue)
{
if(attributeValue == NULL) {
std::cout << "Null pointer received..." << std::endl;
return;
}
switch(attribute_name) {
case ALL_PARAM:
memcpy(attributeValue, &om2jciebuData_ble, sizeof(om2jciebuData_ble));
break;
case TEMP:
*(int16_t *) attributeValue = om2jciebuData_ble.temperature;
break;
case HUMIDITY:
*(int16_t *) attributeValue = om2jciebuData_ble.relative_humidity;
break;
case AMBIENT_LIGHT:
*(int16_t *) attributeValue = om2jciebuData_ble.ambient_light;
break;
case PRESSURE:
*(int32_t *) attributeValue = om2jciebuData_ble.pressure;
break;
case NOISE:
*(int16_t *) attributeValue = om2jciebuData_ble.noise;
break;
case ETVOC:
*(int16_t *) attributeValue = om2jciebuData_ble.eTVOC;
break;
case ECO2:
*(int16_t *) attributeValue = om2jciebuData_ble.eCO2;
break;
case DISCOMFORT_INDEX:
break;
case HEAT_STROKE:
break;
case LED_CONFIGURE:
break;
case ADV_CONFIGURE:
break;
}
}
OM2JCIEBU_BLE::OM2JCIEBU_ERROR_T OM2JCIEBU_BLE::verifyPacket(uint8_t *pkt, int len)
{
if(pkt == NULL) {
std::cout << "Null pointer received..." << std::endl;
return FAILURE;
}
OM2JCIEBU_BLE::OM2JCIEBU_ERROR_T verifyResult = FAILURE;
if(pkt[OM2JCIEBU_BLE_COM_ID_INDEX] == 0xD5) { //Check for Omron company ID
if(pkt[OM2JCIEBU_BLE_COM_ID_INDEX + 1] == 0x02) {
if(pkt[OM2JCIEBU_BLE_DATA_TYPE_INDEX] == 0x01) { // Check for sensor data type
verifyResult = SUCCESS;
} else {
printf("Unable to get sensor data in advertisement packet,Please check advertisement setting\r\n");
verifyResult = ERROR_UNKNOWN ;
}
}
} else {
printf("Unable to get sensor data in advertisement packet,Please check advertisement setting\r\n");
verifyResult = ERROR_UNKNOWN ;
}
return verifyResult;
}
void OM2JCIEBU_BLE::configureSensorLedState(OM2JCIEBU::OM2JCIEBU_LED_SCALE_T state, uint8_t red, uint8_t green, uint8_t blue)
{
std::vector<unsigned char> led_scale;
led_scale.push_back(state);
led_scale.push_back(0x00);
led_scale.push_back(red);
led_scale.push_back(green);
led_scale.push_back(blue);
writePacket(LED_CONFIGURE, led_scale);
}
void OM2JCIEBU_BLE::configureSensorAdvSetting(uint16_t milliseconds, OM2JCIEBU::OM2JCIEBU_ADV_PARAM_T adv_mode)
{
std::vector<unsigned char> advSetting;
uint16_t interval = 0;
interval = milliseconds / OM2JCIEBU_INTERVAL_UNIT;/*calculate interval which is given by user using interval unit */
advSetting.push_back(interval & 0x00FF);
advSetting.push_back(interval >> 8);
advSetting.push_back(adv_mode);
writePacket(ADV_CONFIGURE, advSetting);
}
void OM2JCIEBU_BLE::parseSensorData(uint8_t *data)
{
/* pasre and calculate sensor data and store in sensor data struct*/
if(data == NULL) {
std::cout << "Null pointer received..." << std::endl;
return;
}
om2jciebuData_ble.sequence_number = data[0];
om2jciebuData_ble.temperature = data[1] | data[2] << 8;
om2jciebuData_ble.temperature = om2jciebuData_ble.temperature / 100;
om2jciebuData_ble.relative_humidity = data[3] | data[4] << 8;
om2jciebuData_ble.relative_humidity = om2jciebuData_ble.relative_humidity / 100;
om2jciebuData_ble.ambient_light = data[5] | data[6] << 8;
om2jciebuData_ble.pressure = data[7] | data[8] << 8 | data[9] << 16 | data[10] << 24;
om2jciebuData_ble.pressure = om2jciebuData_ble.pressure / 1000;
om2jciebuData_ble.noise = data[11] | data[12] << 8;
om2jciebuData_ble.noise = om2jciebuData_ble.noise / 100;
om2jciebuData_ble.eTVOC = data[13] | data[14] << 8;
om2jciebuData_ble.eCO2 = data[15] | data[16] << 8;
}
void OM2JCIEBU_BLE::parseAdvSensorData(uint8_t *data)
{
/* pasre and calculate Advertisement data and store in sensor data struct*/
if(data == NULL) {
std::cout << "Null pointer received..." << std::endl;
return;
}
om2jciebuData_ble.sequence_number = data[3];
om2jciebuData_ble.temperature = data[4] | data[5] << 8;
om2jciebuData_ble.temperature = om2jciebuData_ble.temperature / 100;
om2jciebuData_ble.relative_humidity = data[6] | data[7] << 8;
om2jciebuData_ble.relative_humidity = om2jciebuData_ble.relative_humidity / 100;
om2jciebuData_ble.ambient_light = data[8] | data[9] << 8;
om2jciebuData_ble.pressure = data[10] | data[11] << 8 | data[12] << 16 | data[13] << 24;
om2jciebuData_ble.pressure = om2jciebuData_ble.pressure / 1000;
om2jciebuData_ble.noise = data[14] | data[15] << 8;
om2jciebuData_ble.noise = om2jciebuData_ble.noise / 100;
om2jciebuData_ble.eTVOC = data[16] | data[17] << 8;
om2jciebuData_ble.eCO2 = data[18] | data[19] << 8;
}

View File

@ -0,0 +1,230 @@
/*
*
* Author: Hiroyuki Mino <omronsupportupm@omron.com>
* Copyright (c) 2019 Omron Electronic Components - Americas
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*=========================================================================*/
#pragma once
#include <tinyb.hpp>
#include <iostream>
#include <string>
#include <stdexcept>
#include <vector>
#include <thread>
#include <atomic>
#include <csignal>
#include "../2jciebu01.hpp"
/*MACROS and enum */
#define OM2JCIEBU_BLE_DISCOVERY_RETRY 15
#define OM2JCIEBU_BLE_LED_AND_ADV_CONFIGUARTION_SERVICE "ab705110-0a3a-11e8-ba89-0ed5f89f718b"
#define OM2JCIEBU_BLE_LIVE_SENSOR_DATA_SERVICE "ab705010-0a3a-11e8-ba89-0ed5f89f718b"
#define OM2JCIEBU_BLE_COM_ID_INDEX 0x00
#define OM2JCIEBU_BLE_DATA_TYPE_INDEX 0x02
#define VERIFY_PACKET 0
#define DEBUG_LOG 0
#define MAX_UUID_SIZE 64
#define MAX_SENSOR_DATA_SIZE 64
/*=========================================================================*/
namespace upm
{
/**
* @brief 2JCIEBU01 Environment sensor
* @defgroup 2jciebu01 libupm-2jciebu01_ble
* @ingroup Omron USB type
*/
/**
* @library libupm-2jciebu01_ble
* @sensor 2jciebu01
* @comname Environment Sensor Module
* @altname Omron Environment sensor USB type
* @type USB
* @man Omron
* @web https://www.components.omron.com/solutions/mems-sensors/environment-sensor
* @con ble
*
* @brief API for the Omron USB type environment Sensor Module using BLE interface
*
* It is connected via a BLE Interface
*
* @snippet 2jciebu01_ble.cxx Interesting
*/
class OM2JCIEBU_BLE : public OM2JCIEBU
{
public :
/**
* OM2JCIEBU_BLE Constructor, takes the device address as
* an argument
*
* @param device MAC address of Omron Environment Sensor
*/
OM2JCIEBU_BLE(std::string ble_address);
/**
* Get discovery service from Connetced BLE device
*
* @param attribute_name attribute name of sensor
* @return OM2JCIEBU_ERROR_T
*/
OM2JCIEBU_ERROR_T getDiscoveredServices(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name);
/**
* Get omron sensor live data as per request uisng 0x5012 UUID
*
* @param attribute_name Name of attribute
* @param attribute_data Data of attirbute
* @return One of the OM2JCIEBU_ERROR_T values
*/
OM2JCIEBU_ERROR_T getSensorData(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name, void *attribute_data);
/**
* Get omron sensor live data based on advertise payload
*
* @param attribute_name Name of attribute
* @param attribute_data Data of attirbute
* @return One of the OM2JCIEBU_ERROR_T values
*/
OM2JCIEBU_ERROR_T getAdvSensorData(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name, void *attribute_data);
/**
* Set LED configartion of sensor
*
* @param state state for led configuartion
* @param red value of red
* @param green value of green
* @param blue value of blue
*/
void configureSensorLedState(OM2JCIEBU::OM2JCIEBU_LED_SCALE_T state, uint8_t red, uint8_t green, uint8_t blue);
/**
* Set Advertise interval setting of sensor
*
* @param miliseconds interval for Advertise data
* @param adv_mode Advertise mode
*/
void configureSensorAdvSetting(uint16_t milliseconds, OM2JCIEBU::OM2JCIEBU_ADV_PARAM_T adv_mode);
/**
* Disconnect BLE Device
*
* @return Return success or Failure
*
*/
bool removeBleDevice();
private:
BluetoothManager *bleManager = nullptr;
BluetoothDevice *bleSensorTag = nullptr;
BluetoothGattCharacteristic *bleSensorChar = nullptr;
BluetoothGattService *bleService = nullptr;
om2jciebuData_t om2jciebuData_ble;
std::string bleMACaddress;
bool is_BleConnected = false;
/**
*connect BLE Device
*
* @param device_address BLE deivce adddress
*
* @return Return success or Failure
*/
bool connectBleDevice(std::string ble_address);
/**
* Start BLE Discovery
*
* @return Return success or Failure
*/
bool startBleDiscovery();
/**
* Stop BLE Discovery
*
* @return Return success or Failure
*/
bool stopBleDiscovery();
/**
* Get sensor data from global struct.
*
* @param attribute_name attribute_name of sensor data
* @param attributeValue Data of attirbute
*/
void getSensorAttribute(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name, void *attributeValue);
/**
* Verifies the packet header and indicates its valid or not
*
* @param pkt Packet to check
* @param len length of packet
* @return One of the OM2JCIEBU_ERROR_T values
*/
OM2JCIEBU_ERROR_T verifyPacket(uint8_t *pkt, int len);
/**
* Calculate and parse advertise sensor data and store into
* structure
*
* @param data Packet
*
*/
void parseAdvSensorData(uint8_t *data);
/**
* Calculate and parse sensor data and store into
* structure
*
* @param data Packet
*
*/
void parseSensorData(uint8_t *data);
/**
* Write packet over BLE
*
* @param attribute_name attribute_name of sensor
* @param arg_value arg value for write a data over BLE
*
* @return Return success or Failure
*/
bool writePacket(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name, const std::vector<unsigned char> &arg_value);
};
}

View File

@ -0,0 +1,8 @@
%include "../common_top.i"
/* BEGIN Common SWIG syntax ------------------------------------------------- */
%{
#include "2jciebu01_ble.hpp"
%}
%include "2jciebu01_ble.hpp"
/* END Common SWIG syntax */

View File

@ -0,0 +1,29 @@
{
"Library": "2jciebu01_ble",
"Description": "Omron Environment Sensor",
"Sensor Class": {
"OM2JCIEBU_BLE": {
"Name": "API for 2JCIEBU01 Sensor Module using BLE interface",
"Description": "This is the UPM Module for the Omron Environment Sensor Module using BLE interface.",
"Aliases": [""],
"Categories": ["USB"],
"Connections": ["ble"],
"Project Type": ["sensor"],
"Manufacturers": ["Omron"],
"Image": "",
"Examples": {
"C++": ["omron2jciebu01_ble.cxx"]
},
"Platforms": {
"Intel Edison": {
"Notes": ["Might need USB type omron environment sensor"]
}
},
"Urls": {
"Product Pages": ["https://www.components.omron.com/solutions/mems-sensors/environment-sensor"],
"Datasheets": ["https://omronfs.omron.com/en_US/ecb/products/pdf/A279-E1-01.pdf"]
}
}
}
}

View File

@ -0,0 +1,5 @@
set (libname "2jciebu01_ble")
set (libdescription "Omron Environment Sensor")
set (module_src ${libname}.cxx "2jciebu01.cxx")
set (module_hpp ${libname}.hpp "2jciebu01.hpp")
upm_module_init(2jciebu01-usb)

View File

@ -0,0 +1,98 @@
/*
* Author: Hiroyuki Mino <omronsupportupm@omron.com>
* Copyright (c) 2019 Omron Electronic Components - Americas
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <iostream>
#include <string>
#include <stdexcept>
#include "2jciebu01.hpp"
using namespace upm;
using namespace std;
void OM2JCIEBU::getAddress(OM2JCIEBU_ATTRIBUTE_T attribute_name, OM2JCIEBU_INTERFACE_T interface, void *attribute_value)
{
if(attribute_value == NULL) {
std::cout << "Null pointer received..." << std::endl;
return;
}
switch(attribute_name) {
case ALL_PARAM:
case TEMP:
case HUMIDITY:
case AMBIENT_LIGHT:
case PRESSURE:
case NOISE:
case ETVOC:
case ECO2:
case DISCOMFORT_INDEX:
case HEAT_STROKE:
if(interface == USB_TO_UART) //Check for interface
*(uint16_t *)attribute_value = OM2JCIEBU_LIVE_LONG_DATA_READ_ADD_UART;
else
memcpy(attribute_value, OM2JCIEBU_LIVE_LONG_DATA_READ_UUID_BLE, strlen(OM2JCIEBU_LIVE_LONG_DATA_READ_UUID_BLE));
break;
case LED_CONFIGURE:
if(interface == USB_TO_UART)
*(uint16_t *)attribute_value = OM2JCIEBU_LED_CONFIGUARTION_ADD_UART;
else
memcpy(attribute_value, OM2JCIEBU_LED_CONFIGUARTION_UUID_BLE, strlen(OM2JCIEBU_LED_CONFIGUARTION_UUID_BLE));
break;
case ADV_CONFIGURE:
if(interface == USB_TO_UART)
*(uint16_t *)attribute_value = OM2JCIEBU_ADV_CONFIGUARTION_ADD_UART;
else
memcpy(attribute_value, OM2JCIEBU_ADV_CONFIGUARTION_UUID_BLE, strlen(OM2JCIEBU_ADV_CONFIGUARTION_UUID_BLE));
break;
}
}
void OM2JCIEBU::delay(int second)
{
sleep(second);
}
uint16_t OM2JCIEBU::crc_16(uint8_t *data, int length)
{
/* calculate crc_16 for payload */
if(data == NULL) {
std::cout << "Null pointer received..." << std::endl;
return 0;
}
uint16_t crc = OM2JCIEBU_CRC16, l_outeriterator = 0, l_Inneriterator = 0, carrayFlag = 0;
for(l_outeriterator = 0; l_outeriterator < length; l_outeriterator++) {
crc = crc ^ data[l_outeriterator];
for(l_Inneriterator = 0; l_Inneriterator < 8; l_Inneriterator++) {
carrayFlag = crc & 1;
crc = crc >> 1;
if(carrayFlag == 1) {
crc = crc ^ 0xA001;
}
}
}
return crc;
}

View File

@ -0,0 +1,240 @@
/*
* Author: Hiroyuki Mino <omronsupportupm@omron.com>
* Copyright (c) 2019 Omron Electronic Components - Americas
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*=========================================================================*/
#pragma once
#include <string>
#include <iostream>
#include <limits>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <upm/upm_utilities.h>
/*MACROS and enum */
#define OM2JCIEBU_FLASH_LONG_DATA_READ_ADD_UART 0x500E
#define OM2JCIEBU_LIVE_LONG_DATA_READ_ADD_UART 0x5021
#define OM2JCIEBU_LED_CONFIGUARTION_ADD_UART 0x5111
#define OM2JCIEBU_ADV_CONFIGUARTION_ADD_UART 0x5115
#define OM2JCIEBU_LED_CONFIGUARTION_UUID_BLE "ab705111-0a3a-11e8-ba89-0ed5f89f718b"
#define OM2JCIEBU_ADV_CONFIGUARTION_UUID_BLE "ab705115-0a3a-11e8-ba89-0ed5f89f718b"
#define OM2JCIEBU_LIVE_LONG_DATA_READ_UUID_BLE "ab705012-0a3a-11e8-ba89-0ed5f89f718b"
#define OM2JCIEBU_CRC_LENGTH 2
#define OM2JCIEBU_CRC16 0xFFFF
#define OM2JCIEBU_INTERVAL_UNIT 0.625
/*=========================================================================*/
namespace upm
{
/**
* @brief omron 2JCIEBU01 Environment sensor
* @defgroup 2jciebu01 libupm-2jciebu01
* @ingroup Omron USB type
*/
/**
* @library 2jciebu01
* @sensor 2jciebu01
* @comname Environment Sensor Module
* @altname Omron Environment sensor USB type
* @type USB
* @man Omron
* @web https://www.components.omron.com/solutions/mems-sensors/environment-sensor
* @con usb
*
* @brief API for the Omron USB type environment Sensor Module using USB to UART interface
*
* It is connected via a UART at 115200 baud.
*
* @snippet 2jciebu01.cxx Interesting
*/
class OM2JCIEBU
{
public :
typedef enum {
ALL_PARAM,
TEMP,
HUMIDITY,
AMBIENT_LIGHT,
PRESSURE,
NOISE,
ETVOC,
ECO2,
DISCOMFORT_INDEX,
HEAT_STROKE,
LED_CONFIGURE,
ADV_CONFIGURE,
} OM2JCIEBU_ATTRIBUTE_T;
typedef enum {
BLE,
USB_TO_UART
} OM2JCIEBU_INTERFACE_T;
typedef enum {
SENSOR_DATA = 1,
ACCELERATION_DATA,
ACCELERATION_SENSOR_DATA,
ACCELERATION_SENSOR_FLAG,
SERIAL_NUMBER
} OM2JCIEBU_ADV_PARAM_T;
typedef enum {
ERROR_CRC_WRONG = -1,
ERROR_WRONG_COMMAND,
ERROR_WRONG_ADDRESS,
ERROR_WRONG_LENGTH,
ERROR_DATA_RANGE,
ERROR_BUSY,
ERROR_UNKNOWN,
ERROR_CRC_MISMATCH,
FAILURE = 0,
SUCCESS = 1
} OM2JCIEBU_ERROR_T;
typedef enum {
NORMALLY_OFF = 0,
NORMALLY_ON,
TEMP_SACLE,
HUMIDITY_SCALE,
AMBIENT_LIGHT_SCALE,
PRESSURE_SCALE,
NOISE_SCALE,
ETVOC_SCALE,
SI_SCALE,
PGA_SCALE
} OM2JCIEBU_LED_SCALE_T;
typedef struct {
uint8_t sequence_number;
int16_t temperature;
int16_t relative_humidity;
int16_t ambient_light;
int32_t pressure;
int16_t noise;
int16_t eTVOC;
int16_t eCO2;
int16_t discomfort_index;
int16_t heat_stroke;
} __attribute__((packed))om2jciebuData_t;
/**
* OM2JCIEBU destructor
*/
virtual ~OM2JCIEBU() {}
/**
* get address or UUID based on attribute name
*
* @param attribute_name attribute name of sensor
* @param interface Interface name of sensor
* @param attribute_value address value and UUID based on attribute name
*/
void getAddress(OM2JCIEBU_ATTRIBUTE_T attribute_name, OM2JCIEBU_INTERFACE_T interface, void *attribute_value);
/**
* Delay for read sensor data;
*
* @param second second for delay
*/
void delay(int second);
/**
* Calculate crc-16 from the header
* to the end of the payload.
*
* @param data Packet
* @param length length of packet
* @return 16 bit crc of payload
*/
uint16_t crc_16(uint8_t *data, int length);
/**
* Set LED configartion of sensor
*
* @param state state for led configuartion
* @param red value of red
* @param green value of green
* @param blue value of blue
*/
virtual void configureSensorLedState(OM2JCIEBU_LED_SCALE_T state, uint8_t red, uint8_t green, uint8_t blue) = 0;
/**
* Set Advertise configuration of sensor
*
* @param miliseconds interval for Advertise data
* @param adv_mode Advertise mode
*/
virtual void configureSensorAdvSetting(uint16_t milliseconds, OM2JCIEBU_ADV_PARAM_T adv_mode) = 0;
/**
* Calculate and parse sensor data and store into
* Sensor data structure
*
* @param data Packet
*
*/
virtual void parseSensorData(uint8_t *data) = 0;
/**
* Get omron sensor live data as per attribute name
*
* @param attribute_name Name of attribute
* @param attribute_data Data of attirbute
* @return One of the OM2JCIEBU_ERROR_T values
*/
virtual OM2JCIEBU_ERROR_T getSensorData(OM2JCIEBU_ATTRIBUTE_T attribute_name, void *attribute_data) = 0;
/**
* Verifies the packet header and indicates it is valid or not
*
* @param pkt Packet to check
* @param len length of packet
* @return One of the OM2JCIEBU_ERROR_T values
*/
virtual OM2JCIEBU_ERROR_T verifyPacket(uint8_t *pkt, int len) = 0;
};
}

View File

@ -0,0 +1,351 @@
/*
* Author: Hiroyuki Mino <omronsupportupm@omron.com>
* Copyright (c) 2019 Omron Electronic Components - Americas
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <iostream>
#include <string>
#include <stdexcept>
#include "2jciebu01_usb.hpp"
using namespace upm;
using namespace std;
static const int defaultDelay = 1000; // max wait time for read
OM2JCIEBU_UART::OM2JCIEBU_UART(std::string uart_raw, int baud) : m_uart(uart_raw)
{
if(!setupTty(baud))
throw std::runtime_error(std::string(__FUNCTION__) +
": failed to set baud rate to " + std::to_string(baud));
}
bool OM2JCIEBU_UART::setupTty(uint32_t baud)
{
return m_uart.setBaudRate(baud) == mraa::SUCCESS;
}
uint8_t OM2JCIEBU_UART::setMode(int bytesize, mraa::UartParity parity, int stopbits)
{
return m_uart.setMode(bytesize, parity, stopbits);
}
uint8_t OM2JCIEBU_UART::setFlowControl(bool xonxoff, bool rtscts)
{
return m_uart.setFlowcontrol(xonxoff, rtscts);
}
int OM2JCIEBU_UART::readData(char *buffer, int len)
{
if(buffer == NULL) {
std::cout << "Null pointer received..." << std::endl;
return FAILURE;
}
if(!m_uart.dataAvailable(defaultDelay)) //time out for read UART data
return 0;
int rv = m_uart.read(buffer, len);
//check for UART read fail
if(rv < 0)
throw std::runtime_error(std::string(__FUNCTION__) +
": Uart::read() failed: " + string(strerror(errno)));
return rv;
}
int OM2JCIEBU_UART::writeData(char *buffer, int len)
{
if(buffer == NULL) {
std::cout << "Null pointer received..." << std::endl;
return FAILURE;
}
int rv = m_uart.write(buffer, len);
//check for UART write fail
if(rv < 0)
throw std::runtime_error(std::string(__FUNCTION__) +
": Uart::write() failed: " +
string(strerror(errno)));
//check for UART write fail
if(rv == 0)
throw std::runtime_error(std::string(__FUNCTION__) +
": Uart::write() failed, no bytes written");
return rv;
}
int OM2JCIEBU_UART::readCmdPacket(OM2JCIEBU_UART::OM2JCIEBU_ATTRIBUTE_T attribute_name)
{
/* Create a payload as per OMRON uart frame format*/
uint8_t omPkt[OM2JCIEBU_UART_MAX_PKT_LEN] = {0};
uint16_t pktLength = 0, crc = 0, pktIndex = 0, address = 0;
omPkt[pktIndex++] = OM2JCIEBU_UART_HEADER_START;
omPkt[pktIndex++] = OM2JCIEBU_UART_HEADER_END;
pktLength = OM2JCIEBU_CRC_LENGTH + OM2JCIEBU_UART_ADDRESS_LENGTH + OM2JCIEBU_UART_COMMAND_LENGHT;
omPkt[pktIndex++] = pktLength & 0x00FF;
omPkt[pktIndex++] = pktLength >> 8;
omPkt[pktIndex++] = UART_CMD_READ;
getAddress(attribute_name, USB_TO_UART, &address);
omPkt[pktIndex++] = address & 0x00FF;
omPkt[pktIndex++] = address >> 8;
crc = crc_16(omPkt, pktIndex);
omPkt[pktIndex++] = crc & 0x00FF;
omPkt[pktIndex++] = crc >> 8;
return (writeData((char *)omPkt, pktIndex));
}
void OM2JCIEBU_UART::configureSensorAdvSetting(uint16_t milliseconds, OM2JCIEBU::OM2JCIEBU_ADV_PARAM_T adv_mode)
{
uint8_t adv_config[3] = {0};
uint16_t interval;
interval = milliseconds / OM2JCIEBU_INTERVAL_UNIT; /*calculate interval which is given by user using interval unit */
adv_config[0] = interval & 0x00FF;
adv_config[1] = interval >> 8;
adv_config[2] = adv_mode;
writeCmdPacket(ADV_CONFIGURE, adv_config, sizeof(adv_config));
}
void OM2JCIEBU_UART::configureSensorLedState(OM2JCIEBU::OM2JCIEBU_LED_SCALE_T state, uint8_t red, uint8_t green, uint8_t blue)
{
uint8_t led_config[5] = {0};
led_config[0] = state;
led_config[1] = 0x00;
led_config[2] = red;
led_config[3] = green;
led_config[4] = blue;
writeCmdPacket(LED_CONFIGURE, led_config, sizeof(led_config));
}
int OM2JCIEBU_UART::writeCmdPacket(OM2JCIEBU_UART::OM2JCIEBU_ATTRIBUTE_T attribute_name, uint8_t *data, uint16_t length)
{
/* Create a frame formate for write a data on UART as per common frame formate*/
if(data == NULL) {
std::cout << "Null pointer received..." << std::endl;
return FAILURE;
}
uint8_t omPkt[OM2JCIEBU_UART_MAX_PKT_LEN] = {0};
uint16_t pktLength = 0, crc = 0, pktIndex = 0, l_iterator = 0, address = 0;
omPkt[pktIndex++] = OM2JCIEBU_UART_HEADER_START;
omPkt[pktIndex++] = OM2JCIEBU_UART_HEADER_END;
pktLength = OM2JCIEBU_CRC_LENGTH + OM2JCIEBU_UART_ADDRESS_LENGTH + OM2JCIEBU_UART_COMMAND_LENGHT + length;
omPkt[pktIndex++] = pktLength & 0x00FF;
omPkt[pktIndex++] = pktLength >> 8;
omPkt[pktIndex++] = UART_CMD_WRITE;
getAddress(attribute_name, USB_TO_UART, &address);
omPkt[pktIndex++] = address & 0x00FF;
omPkt[pktIndex++] = address >> 8;
for(l_iterator = 0; l_iterator < length; l_iterator++) {
omPkt[pktIndex++] = data[l_iterator];
}
crc = crc_16(omPkt, pktIndex);
omPkt[pktIndex++] = crc & 0x00FF;
omPkt[pktIndex++] = crc >> 8;
return (writeData((char *)omPkt, pktIndex));
}
void OM2JCIEBU_UART::getSensorAttribute(OM2JCIEBU_ATTRIBUTE_T attribute_name, void *attributeValue)
{
/* Assign sensor value attributes to void pointer*/
if(attributeValue == NULL) {
std::cout << "Null pointer received..." << std::endl;
return;
}
switch(attribute_name) {
case ALL_PARAM:
memcpy(attributeValue, &om2jciebuData_uart, sizeof(om2jciebuData_uart));
break;
case TEMP:
*(int16_t *) attributeValue = om2jciebuData_uart.temperature;
break;
case HUMIDITY:
*(int16_t *) attributeValue = om2jciebuData_uart.relative_humidity;
break;
case AMBIENT_LIGHT:
*(int16_t *) attributeValue = om2jciebuData_uart.ambient_light;
break;
case PRESSURE:
*(int32_t *) attributeValue = om2jciebuData_uart.pressure;
break;
case NOISE:
*(int16_t *) attributeValue = om2jciebuData_uart.noise;
break;
case ETVOC:
*(int16_t *) attributeValue = om2jciebuData_uart.eTVOC;
break;
case ECO2:
*(int16_t *) attributeValue = om2jciebuData_uart.eCO2;
break;
case DISCOMFORT_INDEX:
*(int16_t *) attributeValue = om2jciebuData_uart.discomfort_index;
break;
case HEAT_STROKE:
*(int16_t *) attributeValue = om2jciebuData_uart.heat_stroke;
break;
case LED_CONFIGURE:
break;
case ADV_CONFIGURE:
break;
}
}
OM2JCIEBU_UART::OM2JCIEBU_ERROR_T OM2JCIEBU_UART::getSensorData(OM2JCIEBU_ATTRIBUTE_T attribute_name, void *attribute_data)
{
if(attribute_data == NULL) {
std::cout << "Null pointer received..." << std::endl;
return FAILURE;
}
//create a payload frame for read sensor data
readCmdPacket(attribute_name);
char buf[OM2JCIEBU_UART_MAX_READ_PKT_LEN];
uint8_t pkt[OM2JCIEBU_UART_MAX_PKT_LEN];
int rv;
int8_t pkt_index = 0, idx = 0;
OM2JCIEBU_UART::OM2JCIEBU_ERROR_T verifyResult = FAILURE;
//read from UART
while(true) {
rv = readData(buf, OM2JCIEBU_UART_MAX_READ_PKT_LEN);
if(rv > 0) {
for(idx = 0; idx < rv; idx++)
pkt[pkt_index++] = buf[idx];
} else {
verifyResult = verifyPacket(pkt, pkt_index);
if(verifyResult == SUCCESS) {
break;
} else {
return verifyResult;
}
}
}
//calculate a data and store in struct
parseSensorData(pkt);
//copy data to user provided pointer
getSensorAttribute(attribute_name, attribute_data);
return verifyResult;
}
OM2JCIEBU_UART::OM2JCIEBU_ERROR_T OM2JCIEBU_UART::verifyPacket(uint8_t *pkt, int len)
{
if(pkt == NULL) {
std::cout << "Null pointer received..." << std::endl;
return FAILURE;
}
uint16_t crc = 0;
OM2JCIEBU_UART::OM2JCIEBU_ERROR_T verifyResult = FAILURE;
//Verify a data which is read from UART buffer
if((pkt[OM2JCIEBU_UART_COMMAND_INDEX] & 0xF0) == 0x80) { //Check for error in payload
if(pkt[OM2JCIEBU_UART_COMMAND_ERROR_CODE_INDEX] == ERROR_UART_CRC_WRONG) {
std::cout << "Error CRC wrong" << std::endl;
verifyResult = ERROR_CRC_WRONG;
} else if(pkt[OM2JCIEBU_UART_COMMAND_ERROR_CODE_INDEX] == ERROR_UART_WRONG_COMMAND) {
std::cout << "Error Invalid Command" << std::endl;
verifyResult = ERROR_WRONG_COMMAND;
} else if(pkt[OM2JCIEBU_UART_COMMAND_ERROR_CODE_INDEX] == ERROR_UART_WRONG_ADDRESS) {
std::cout << "Error Invalid Address" << std::endl;
verifyResult = ERROR_WRONG_ADDRESS;
} else if(pkt[OM2JCIEBU_UART_COMMAND_ERROR_CODE_INDEX] == ERROR_UART_WRONG_LENGTH) {
std::cout << "Error Invalid Length" << std::endl;
verifyResult = ERROR_WRONG_LENGTH;
} else if(pkt[OM2JCIEBU_UART_COMMAND_ERROR_CODE_INDEX] == ERROR_UART_DATA_RANGE) {
std::cout << "Error Invalid Data Range" << std::endl;
verifyResult = ERROR_DATA_RANGE;
} else if(pkt[OM2JCIEBU_UART_COMMAND_ERROR_CODE_INDEX] == ERROR_UART_BUSY) {
std::cout << "Uart is BUSY" << std::endl;
verifyResult = ERROR_BUSY;
}
} else if((pkt[OM2JCIEBU_UART_COMMAND_INDEX] & 0xFF) == 0xFF) { //Check for unknow error in UART frame
std::cout << "Invalid reponse" << std::endl;
verifyResult = ERROR_UNKNOWN;
} else {
crc = crc_16(pkt, (len - OM2JCIEBU_CRC_LENGTH)); //Check for CRC which is read from UART frame
if(pkt[len - OM2JCIEBU_CRC_LENGTH] == (crc & 0x00FF) && pkt[len - 1] == crc >> 8) {
verifyResult = SUCCESS;
} else {
std::cout << "Does not match CRC" << std::endl;
verifyResult = ERROR_CRC_MISMATCH;
}
}
return verifyResult;
}
void OM2JCIEBU_UART::parseSensorData(uint8_t *data)
{
if(data == NULL) {
std::cout << "Null pointer received..." << std::endl;
return;
}
//Parse data after payload verfication
om2jciebuData_uart.sequence_number = data[7];
om2jciebuData_uart.temperature = data[8] | data[9] << 8;
om2jciebuData_uart.temperature = om2jciebuData_uart.temperature / 100;
om2jciebuData_uart.relative_humidity = data[10] | data[11] << 8;
om2jciebuData_uart.relative_humidity = om2jciebuData_uart.relative_humidity / 100;
om2jciebuData_uart.ambient_light = data[12] | data[13] << 8;
om2jciebuData_uart.pressure = data[14] | data[15] << 8 | data[16] << 16 | data[17] << 24;
om2jciebuData_uart.pressure = om2jciebuData_uart.pressure / 1000;
om2jciebuData_uart.noise = data[18] | data[19] << 8;
om2jciebuData_uart.noise = om2jciebuData_uart.noise / 100;
om2jciebuData_uart.eTVOC = data[20] | data[21] << 8;
om2jciebuData_uart.eCO2 = data[22] | data[23] << 8;
om2jciebuData_uart.discomfort_index = data[24] | data[25] << 8;
om2jciebuData_uart.discomfort_index = om2jciebuData_uart.discomfort_index / 100;
om2jciebuData_uart.heat_stroke = data[26] | data[27] << 8;
om2jciebuData_uart.heat_stroke = om2jciebuData_uart.heat_stroke / 100;
}

View File

@ -0,0 +1,247 @@
/*
*
* Author: Hiroyuki Mino <omronsupportupm@omron.com>
* Copyright (c) 2019 Omron Electronic Components - Americas
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*=========================================================================*/
#pragma once
#include "mraa.hpp"
#include "2jciebu01.hpp"
/*MACROS and enum */
// protocol start codes
#define OM2JCIEBU_UART_HEADER_START 0x52
#define OM2JCIEBU_UART_HEADER_END 0x42
#define OM2JCIEBU_UART_MAX_PKT_LEN 256
#define OM2JCIEBU_UART_MAX_READ_PKT_LEN 10
#define OM2JCIEBU_UART_COMMAND_LENGHT 1
#define OM2JCIEBU_UART_ADDRESS_LENGTH 2
#define OM2JCIEBU_UART_HEADER_LENGTH 2
#define OM2JCIEBU_UART_COMMAND_INDEX 0x04
#define OM2JCIEBU_UART_COMMAND_ERROR_CODE_INDEX 0x07
/*=========================================================================*/
namespace upm
{
/**
* @brief 2JCIEBU01 Environment sensor
* @defgroup 2jciebu01 libupm-2jciebu01_usb
* @ingroup Omron USB type
*/
/**
* @library libupm-2jciebu01_usb
* @sensor 2jciebu01
* @comname Environment Sensor Module
* @altname Omron Environment sensor USB type
* @type USB
* @man Omron
* @web https://www.components.omron.com/solutions/mems-sensors/environment-sensor
* @con usb
*
* @brief API for the Omron USB type environment Sensor Module using USB to UART interface
*
* It is connected via a UART at 115200 baud.
*
* @snippet 2jciebu01_usb.cxx Interesting
*/
class OM2JCIEBU_UART : public OM2JCIEBU
{
public :
typedef enum {
UART_CMD_READ = 0x01,
UART_CMD_WRITE = 0x02
} OM2JCIEBU_UART_COMMAND_T;
typedef enum {
ERROR_UART_CRC_WRONG = 0x01,
ERROR_UART_WRONG_COMMAND = 0x02,
ERROR_UART_WRONG_ADDRESS = 0x03,
ERROR_UART_WRONG_LENGTH = 0x04,
ERROR_UART_DATA_RANGE = 0x05,
ERROR_UART_BUSY = 0x06,
ERROR_UART_UNKNOWN = 0XFF
} OM2JCIEBU_UART_ERROR_T;
typedef enum {
PARITY_UART_NONE = 0,
PARITY_UART_EVEN = 1,
PARITY_UART_ODD = 2,
PARITY_UART_MARK = 3,
PARITY_UART_SPACE = 4
} OM2JCIEBU_UART_PARITY_T;
/**
* OM2JCIEBU_UART Constructor, takes a string to the path of the serial
* interface that is needed.
*
* @param uart File path (/dev/ttyXXX to uart
* @param baud Desired baud rate
*/
OM2JCIEBU_UART(std::string path, int baud = 115200);
/**
* Sets up proper tty I/O modes and the baud rate. For this device,
* the default baud rate is 115200.
*
* @param baud Desired baud rate.
* @return True if successful
*/
bool setupTty(uint32_t baud = 115200);
/**
* Set the transfer mode
* For example setting the mode to 8N1 would be
* "dev.setMode(8,PARITY_NONE , 1)"
*
* @param bytesize data bits
* @param parity Parity bit setting
* @param stopbits stop bits
*
* @return Return success or Failure
*/
uint8_t setMode(int bytesize, mraa::UartParity parity, int stopbits);
/**
* Set the flowcontrol
*
* @param xonxoff XON/XOFF Software flow control.
* @param rtscts RTS/CTS out of band hardware flow control
* @return Return success or Failure
*/
uint8_t setFlowControl(bool xonxoff, bool rtscts);
/**
* Get omron sensor live data as per request
*
* @param attribute_name Name of attribute
* @param attribute_data Data of attirbute
* @return One of the OM2JCIEBU_ERROR_T values
*/
OM2JCIEBU_ERROR_T getSensorData(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name, void *attribute_data);
/**
* Set LED configartion of sensor
*
* @param state state for led configuartion
* @param red value of red
* @param green value of green
* @param blue value of blue
*/
void configureSensorLedState(OM2JCIEBU::OM2JCIEBU_LED_SCALE_T state, uint8_t red, uint8_t green, uint8_t blue);
/**
* Set Advertise interval setting of sensor
*
* @param miliseconds interval for Advertise data
* @param adv_mode Advertise mode
*/
void configureSensorAdvSetting(uint16_t milliseconds, OM2JCIEBU::OM2JCIEBU_ADV_PARAM_T adv_mode);
private:
mraa::Uart m_uart;
om2jciebuData_t om2jciebuData_uart;
/**
* Composes write command packet and Writes the data
* in the buffer to the device
*
* @param attribute_name Attribute name of sensor
* @param data data for write on particular address
* @param length length of data
* @return Number of bytes written
*/
int writeCmdPacket(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name, uint8_t *data, uint16_t length);
/**
* Composes read command packet and Writes the data
* in the buffer to the device
*
* @param attribute_name Attribute name of sensor
* @return Number of bytes written
*/
int readCmdPacket(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name);
/**
* Get sensor data from global struct.
*
* @param attributeValue Data of attirbute
*
*/
void getSensorAttribute(OM2JCIEBU::OM2JCIEBU_ATTRIBUTE_T attribute_name, void *attributeValue);
/**
* Writes the data in the buffer to the device
*
* @param buffer Buffer to hold the data read
* @param len Length of the buffer
* @return Number of bytes written
*/
int writeData(char *buffer, int len);
/**
* Reads any available data in a user-supplied buffer. Note: the
* call blocks until data is available to be read. Use
* dataAvailable() to determine whether there is data available
* beforehand, to avoid blocking.
*
* @param buffer Buffer to hold the data read
* @param len Length of the buffer
* @return Number of bytes read
*/
int readData(char *buffer, int len);
/**
* Verifies the packet header and indicates it is valid or not
*
* @param pkt Packet to check
* @param len length of packet
* @return One of the OM2JCIEBU_ERROR_T values
*/
OM2JCIEBU_ERROR_T verifyPacket(uint8_t *pkt, int len);
/**
* Calculate and parse sensor data and store into
* Sensor data structure
*
* @param data Packet
*
*/
void parseSensorData(uint8_t *data);
};
}

View File

@ -0,0 +1,8 @@
%include "../common_top.i"
/* BEGIN Common SWIG syntax ------------------------------------------------- */
%{
#include "2jciebu01_usb.hpp"
%}
%include "2jciebu01_usb.hpp"
/* END Common SWIG syntax */

View File

@ -0,0 +1,35 @@
{
"Library": "2jciebu01_usb",
"Description": "Omron USB type enviroment sensor",
"Sensor Class": {
"OM2JCIEBU_UART": {
"Name": "API for 2JCIEBU01 Sensor Module using USB to UART interface",
"Description": "This is the UPM Module for the Omron Enviroment Sensor Module using USB to UART interface.",
"Aliases": [""],
"Categories": ["USB"],
"Connections": ["uart"],
"Project Type": ["sensor"],
"Manufacturers": ["Omron"],
"Image": "",
"Examples": {
"C++": ["omron2jciebu01_usb.cxx"]
},
"Specifications": {
"Baud Rate": {
"unit" : "bps",
"default": 115200
}
},
"Platforms": {
"Intel Edison": {
"Notes": ["Might need USB type omron enviroment sensor"]
}
},
"Urls": {
"Product Pages": ["https://www.components.omron.com/solutions/mems-sensors/environment-sensor"],
"Datasheets": ["https://omronfs.omron.com/en_US/ecb/products/pdf/A279-E1-01.pdf"]
}
}
}
}

View File

@ -0,0 +1,5 @@
set (libname "2jciebu01_usb")
set (libdescription "Omron Environment Sensor")
set (module_src ${libname}.cxx "2jciebu01.cxx")
set (module_hpp ${libname}.hpp "2jciebu01.hpp")
upm_module_init(mraa utilities-c)