Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: ICE-Application/src/ConfigurationHandler/Controls/SensorErrorControl.cpp
- Revision:
- 2:02cb20446785
- Parent:
- 1:b2e90cda7a5a
diff -r b2e90cda7a5a -r 02cb20446785 ICE-Application/src/ConfigurationHandler/Controls/SensorErrorControl.cpp
--- a/ICE-Application/src/ConfigurationHandler/Controls/SensorErrorControl.cpp Tue Jan 24 19:06:45 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,418 +0,0 @@
-/******************************************************************************
-*
-* File: SensorErrorControl.cpp
-* Desciption: ICE Sensor Error Control class implementation
-*
-*****************************************************************************/
-#include "SensorErrorControl.h"
-#include "cJSON.h"
-#include "ModbusMasterApi.h"
-#include "utilities.h"
-#include "ICELog.h"
-#include <string>
-#include <iostream>
-#include <iomanip>
-#include <stdarg.h>
-
-using namespace std;
-
-// for debugging - this can be set via the console command:
-// "debug-se 1
-bool debugSensorError = false;
-
-static void debug(const char *fmt, ...)
-{
- if ( debugSensorError ) {
- va_list vargs;
- va_start(vargs, fmt);
- vfprintf(stdout, fmt, vargs);
- va_end(vargs);
- }
-}
-
-//
-// method: load
-// description: load data from the control file
-//
-// @param[in] _controlFile -> the control file
-// @return true if loaded; false otherwise
-//
-bool SensorErrorControl::load(const std::string _controlFile)
-{
- controlFile = _controlFile;
-
- // read the data into a buffer
- char dataBuf[MAX_FILE_SIZE];
-
- bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf));
- if ( rc != true ) {
- logError("%s: failed to read %s", __func__, controlFile.c_str());
- // caller should destroy the object
- return false;
- }
-
- // validate the JSON formatted control data
- if ( !validateControlData(dataBuf) ) {
- logError("%s: failed to validate control data", __func__);
- return false;
- }
-
- // copy the control data
- copyControlData(dataBuf);
-
- ModbusValue val;
- // validate the input
- if ( ModbusMasterReadRegister(input, &val) == false ) {
- logError("%s failed to find input %s", id.c_str(), input.c_str());
- return false;
- }
-
- isVirtualOutput = Util_isVirtualOutput(output) ? true : false;
- return true;
-}
-
-//
-// @method: validateControlData
-// @description: vaqlidate the JSON formatted string
-//
-// @param[in] buf -> JSON formatted string
-// @param[out] none
-// @return true if valid; false otherwise
-//
-bool SensorErrorControl::validateControlData(const char *buf)
-{
- bool rc = true;
-
- // parse the data
- cJSON * root = cJSON_Parse(buf);
-
- if ( !cJSON_HasObjectItem(root, "id") ||
- !cJSON_HasObjectItem(root, "priority") ||
- !cJSON_HasObjectItem(root, "input") ||
- !cJSON_HasObjectItem(root, "output") ||
- !cJSON_HasObjectItem(root, "dutyCycle") ||
- !cJSON_HasObjectItem(root, "interval") ) {
- logError("%s: control file is missing expected tags", __func__);
- rc = false;
- }
-
- cJSON_Delete(root);
- return rc;
-}
-
-//
-// method: copyControlData
-// description: copy the data from the control file to the object
-//
-// @param[in] buf -> JSON formatted string
-// @param[out] none
-// @return none
-//
-void SensorErrorControl::copyControlData(const char *buf)
-{
- cJSON *root = cJSON_Parse(buf);
-
- id = cJSON_GetObjectItem(root, "id")->valuestring;
- priority = atoi(cJSON_GetObjectItem(root, "priority")->valuestring);
- input = cJSON_GetObjectItem(root, "input")->valuestring;
- output = cJSON_GetObjectItem(root, "output")->valuestring;
- dutyCycle.dutyCycle = atoi(cJSON_GetObjectItem(root, "dutyCycle")->valuestring);
- dutyCycle.interval = atoi(cJSON_GetObjectItem(root, "interval")->valuestring);
-
- cJSON_Delete(root);
-}
-
-//
-// @method: start
-// @description: put the control in the start state
-//
-// @param[in] none
-// @param[out] none
-// @return none
-//
-void SensorErrorControl::start(void)
-{
- currentState = STATE_START;
-}
-
-//
-// @method update
-// @description run the simplified state machine
-//
-// @param[in] none
-// @param[out] none
-// @return OK on success; error otherwise
-//
-SensorErrorControlError_t SensorErrorControl::update(void)
-{
- SensorErrorControlError_t rc = SENSOR_ERROR_CONTROL_OK;
-
- switch (this->currentState) {
- case STATE_INIT:
- // do nothing: control must be programmatically started
- break;
- case STATE_START:
- if ( this->isSensorError() ) {
- if ( dutyCycle.dutyCycle > 0 ) {
- this->startDutyTimer();
- this->currentState = STATE_DUTY_CYCLE_ON;
- sendMailToOutput(ACTION_CONTROL_ON);
- debug("\r%s: [STARTUP]->sensor error->[DUTY_CYCLE_ON] time=%lu\n", id.c_str(), time(0));
- } else {
- // this is a fixed-off state
- this->stopDutyTimer(); // probably not needed
- this->currentState = STATE_DUTY_CYCLE_OFF;
- // tell the output task to turn off the relay
- sendMailToOutput(ACTION_CONTROL_OFF);
- debug("\r%s: [STARTUP]->sensor error (no duty)->[DUTY_CYCLE_OFF] %lu\n", id.c_str(), time(0));
- }
- } else {
- // input signal is OK
- debug("\r%s: [STARTUP]->OK->[OFF] %lu\n", id.c_str(), time(0));
- this->currentState = STATE_CONTROL_OFF;
- }
- break;
- case STATE_CONTROL_OFF:
- if ( isSensorError() ) {
- if ( dutyCycle.dutyCycle > 0 ) {
- this->startDutyTimer();
- this->currentState = STATE_DUTY_CYCLE_ON;
- sendMailToOutput(ACTION_CONTROL_ON);
- debug("\r%s: [STARTUP]->sensor error->[DUTY_CYCLE_ON] %lu\n", id.c_str(), time(0));
- } else {
- // this is a fixed off state
- this->stopDutyTimer(); // probably not needed
- this->currentState = STATE_DUTY_CYCLE_OFF;
- // tell the output task to turn off the relay
- sendMailToOutput(ACTION_CONTROL_OFF);
- debug("\r%s: [STARTUP]->sensor error (no duty)->[DUTY_CYCLE_OFF] %lu\n", id.c_str(), time(0));
- }
- } else {
- // input signal is OK, so don't do anything
- }
- break;
- case STATE_DUTY_CYCLE_ON:
- if ( !isSensorError() ) {
- this->stopDutyTimer();
- this->currentState = STATE_CONTROL_OFF;
- this->unregisterControl();
- debug("\r%s: [DUTY_CYCLE_ON]->no error->[OFF] %lu\n", id.c_str(), time(0));
-
- } else if ( dutyOnExpired() )
- if ( dutyCycle.dutyCycle < 100 ) {
- this->currentState = STATE_DUTY_CYCLE_OFF;
- sendMailToOutput(ACTION_CONTROL_OFF);
- debug("\r%s: [DUTY_CYCLE_ON]->on expired->[DUTY_CYCLE_OFF] %lu\n", id.c_str(), time(0));
- } else {
- // fixed-on state
- // do nothing - we'll need to wait for the sensor error
- // to clear before something can happen
- }
- break;
- case STATE_DUTY_CYCLE_OFF:
- if ( !isSensorError() ) {
- // there is no sensor error, so unregister the control and cleanup
- this->stopDutyTimer();
- this->currentState = STATE_CONTROL_OFF;
- this->unregisterControl();
- debug("\r%s: [DUTY_CYCLE_OFF]->no error->[OFF] %lu\n", id.c_str(), time(0));
- stopDutyTimer();
- } else if ( dutyOffExpired() ) {
- if ( dutyCycle.dutyCycle > 0 ) {
- // we go back to the OFF state so the start and expiration
- // times are recalculated
- this->currentState = STATE_CONTROL_OFF;
- sendMailToOutput(ACTION_CONTROL_OFF);
- debug("\r%s: [DUTY_CYCLE_OFF]->off expired->[OFF] %lu\n", id.c_str(), time(0));
- } else {
- // fixed-off state
- // do nothing - we'll need to wait for the sensor error
- // to clear before something can happen
- }
- }
- break;
- default:
- logError("%s: unknown state\n", __func__);
- rc = SENSOR_ERROR_CONTROL_UNK_STATE;
- break;
- }
- return rc;
-}
-
-//
-// @method: isSensorError
-// @description: reads the modbus register to get the error condition of
-// the input signal
-//
-// @param[in] none
-// @param[out] none
-// @return true if in error; false otherwise
-//
-bool SensorErrorControl::isSensorError()
-{
- ModbusValue val;
-
- if ( ModbusMasterReadRegister(this->input, &val) != true ) {
- logError("Failed to read %s\n", this->input.c_str());
- return true;
- } else if ( val.errflag ) {
- // input is in sensor error
- return true;
- }
- return false;
-}
-
-//
-// @method: dutyOnExpired
-// @description: returns true of duty ON time expired
-//
-// @param[in] none
-// @param[out] none
-// @return true if expired; false otherwise
-//
-bool SensorErrorControl::dutyOnExpired(void)
-{
- return (time(0) >= duty_timer.offTime);
-}
-
-//
-// @method: dutyOffExpired
-// @description: returns true of duty OFF time expired
-//
-// @param[in] none
-// @param[out] none
-// @return true if expired; false otherwise
-//
-bool SensorErrorControl::dutyOffExpired(void)
-{
- return (duty_timer.expirationTime < time(0));
-}
-
-//
-// method: startDutyTimer
-// descrption: start the sensor error duty-timer
-//
-// @param none
-// @return none
-//
-void SensorErrorControl::startDutyTimer(void)
-{
- unsigned long currentTime = time(0);
- unsigned long period = dutyCycle.interval * 60;
-
- duty_timer.offTime = currentTime + ((double)period * ((double)dutyCycle.dutyCycle/100.0));
- duty_timer.expirationTime = currentTime + period;
-
- debug("\r%s:%s-> currentTime = %lu\n", __func__, id.c_str(), currentTime);
- debug("\r%s:%s-> off Time = %lu\n", __func__, id.c_str(), duty_timer.offTime);
- debug("\r%s:%s-> expiration = %lu\n", __func__, id.c_str(), duty_timer.expirationTime);
-}
-
-//
-// method: stopDutyTimer
-// descrption: stop the sensor error duty-timer
-//
-// @param none
-// @return none
-//
-void SensorErrorControl::stopDutyTimer(void)
-{
- memset(&duty_timer, 0, sizeof(duty_timer));
-}
-
-//
-// method: sendMailToOutput
-// description: send a message to the output thread
-//
-// @param[in] action -> on, off, etc.
-// @param[out] none
-// @return
-//
-void SensorErrorControl::sendMailToOutput(OutputAction action)
-{
-
- if ( isVirtualOutput ) {
- debug("%s:%s updating the virtual output %s\n", __func__, id.c_str(), output.c_str());
- ModbusMasterWriteRegister(this->output,
- (action == ACTION_CONTROL_ON) ? 1.0 : 0.0);
- } else {
- debug("%s:%s sensor error control attempting to send action %d\n",
- __func__, id.c_str(), action);
-
- OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
- memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
- output_mail->action = action;
- output_mail->controlType = CONTROL_SENSOR_ERROR;
- output_mail->priority = this->priority;
-
- strncpy(output_mail->input_tag, this->input.c_str(), sizeof(output_mail->input_tag)-1);
- strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
- strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-
- OutputMasterMailBox.put(output_mail);
- }
-}
-
-//
-// @method: unregisterControl
-// @description: unregister the control with the output task
-//
-// @param[in] none
-// @param[out] none
-// @return none
-//
-void SensorErrorControl::unregisterControl(void)
-{
- if ( isVirtualOutput ) {
- debug("%s: %s attempting to unregister virtual output %s\n", __func__, id.c_str(), output.c_str());
- ModbusMasterWriteRegister(output, 0.0);
- } else {
- debug("%s: %s attempting to unregister output %s\n",
- __func__, id.c_str(), output.c_str());
-
- OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc();
- memset(output_mail, 0, sizeof(OutputControlMsg_t));
-
- output_mail->action = ACTION_CONTROL_UNREGISTER;
- output_mail->controlType = CONTROL_FAILSAFE;
- output_mail->priority = this->priority;
- strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1);
- strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1);
-
- OutputMasterMailBox.put(output_mail);
- }
-}
-
-//
-// @method: display
-// @description: show the pertinents
-//
-// @param[in] none
-// @param[out] none
-// @return none
-//
-void SensorErrorControl::display(void)
-{
- const char *mapper[] = { "INIT",
- "START",
- "OFF",
- "DUTY CYCLE ON",
- "DUTY CYCLE OFF",
- "invalid"
- };
-
- printf("\r\n");
- std::cout << left << setw(10) << setfill(' ') << "sensor error: ";
- std::cout << left << setw(40) << setfill(' ') << controlFile;
- std::cout << left << setw(20) << setfill(' ') << id;
- std::cout << left << setw(6) << setfill(' ') << priority;
- std::cout << left << setw(20) << setfill(' ') << input;
- std::cout << left << setw(20) << setfill(' ') << output;
- std::cout << left << setw(16) << setfill(' ') << mapper[currentState];
- std::cout << "duty cycle: " << left << setw(4) << setfill(' ') << dutyCycle.dutyCycle;
- std::cout << "interval: " << left << setw(4) << setfill(' ') << dutyCycle.interval;
-
- std::cout.flush();
-}
-