mirror of
https://github.com/peterantypas/maiana.git
synced 2025-05-15 23:10:11 -07:00
315 lines
8.3 KiB
C++
315 lines
8.3 KiB
C++
/*
|
|
* CommandProcessor.cpp
|
|
*
|
|
* Created on: Jun 24, 2016
|
|
* Author: peter
|
|
*/
|
|
|
|
#include "CommandProcessor.hpp"
|
|
#include <cstring>
|
|
#include "EEPROM.hpp"
|
|
#include <cstdio>
|
|
#include "globals.h"
|
|
#include "stm32f30x.h"
|
|
|
|
CommandProcessor &
|
|
CommandProcessor::instance()
|
|
{
|
|
static CommandProcessor __instance;
|
|
return __instance;
|
|
}
|
|
|
|
CommandProcessor::CommandProcessor()
|
|
{
|
|
|
|
}
|
|
|
|
void
|
|
CommandProcessor::init()
|
|
{
|
|
EventQueue::instance ().addObserver (this, REQUEST_EVENT | RESET_EVENT);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::processEvent(const Event &e)
|
|
{
|
|
if (e.type == RESET_EVENT) {
|
|
NVIC_SystemReset ();
|
|
return;
|
|
}
|
|
|
|
switch (e.request.operation) {
|
|
case OP_GET:
|
|
if (strcmp (e.request.field, "mmsi") == 0)
|
|
returnMMSI ();
|
|
else if (strcmp (e.request.field, "name") == 0)
|
|
returnName ();
|
|
else if (strcmp (e.request.field, "callsign") == 0)
|
|
returnCallSign ();
|
|
else if (strcmp (e.request.field, "beam") == 0)
|
|
returnBeam ();
|
|
else if (strcmp (e.request.field, "length") == 0)
|
|
returnLength ();
|
|
else if (strcmp (e.request.field, "mode") == 0)
|
|
returnMode ();
|
|
else if (strcmp (e.request.field, "vesseldata") == 0)
|
|
returnVesselData ();
|
|
else if (strcmp (e.request.field, "version") == 0)
|
|
returnVersion ();
|
|
else if (strcmp (e.request.field, "status") == 0)
|
|
returnStatus ();
|
|
else
|
|
sendError ("Unknown field");
|
|
break;
|
|
case OP_SET:
|
|
if (strcmp (e.request.field, "mmsi") == 0)
|
|
setMMSI (atoi (e.request.value));
|
|
else if (strcmp (e.request.field, "name") == 0)
|
|
setName (e.request.value);
|
|
else if (strcmp (e.request.field, "callsign") == 0)
|
|
setCallSign (e.request.value);
|
|
else if (strcmp (e.request.field, "beam") == 0)
|
|
setBeam (atoi (e.request.value));
|
|
else if (strcmp (e.request.field, "length") == 0)
|
|
setLength (atoi (e.request.value));
|
|
else if (strcmp (e.request.field, "mode") == 0)
|
|
setMode (e.request.value);
|
|
else if (strcmp (e.request.field, "vesseldata") == 0)
|
|
setVesselData (e.request.value);
|
|
else
|
|
sendError ("Unknown field");
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
void
|
|
CommandProcessor::sendError(const char *err)
|
|
{
|
|
Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
|
|
reply->response.success = false;
|
|
strcpy (reply->response.data, err);
|
|
EventQueue::instance ().push (reply);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::sendEmptyReply(bool success)
|
|
{
|
|
Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
|
|
reply->response.success = success;
|
|
reply->response.data[0] = 0;
|
|
EventQueue::instance ().push (reply);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::returnVersion()
|
|
{
|
|
Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
|
|
reply->response.success = true;
|
|
strcpy (reply->response.data, REVISION);
|
|
EventQueue::instance ().push (reply);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::returnMMSI()
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
|
|
Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
|
|
reply->response.success = true;
|
|
sprintf (reply->response.data, "%lu", data.mmsi);
|
|
EventQueue::instance ().push (reply);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::returnCallSign()
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
|
|
Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
|
|
reply->response.success = true;
|
|
sprintf (reply->response.data, "%s", data.callsign);
|
|
EventQueue::instance ().push (reply);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::returnName()
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
|
|
Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
|
|
reply->response.success = true;
|
|
sprintf (reply->response.data, "%s", data.name);
|
|
EventQueue::instance ().push (reply);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::returnBeam()
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
|
|
Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
|
|
reply->response.success = true;
|
|
sprintf (reply->response.data, "%d", data.beam);
|
|
EventQueue::instance ().push (reply);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::returnLength()
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
|
|
Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
|
|
reply->response.success = true;
|
|
sprintf (reply->response.data, "%d", data.len);
|
|
EventQueue::instance ().push (reply);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::returnMode()
|
|
{
|
|
}
|
|
|
|
void
|
|
CommandProcessor::returnVesselData()
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
|
|
Event *reply = EventPool::instance ().newEvent (RESPONSE_EVENT);
|
|
reply->response.success = true;
|
|
|
|
sprintf (reply->response.data, "%lu,%s,%s,%d,%d", data.mmsi, data.name,
|
|
data.callsign, data.beam, data.len);
|
|
EventQueue::instance ().push (reply);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::returnStatus()
|
|
{
|
|
}
|
|
|
|
void
|
|
CommandProcessor::setMMSI(uint32_t mmsi)
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
data.mmsi = mmsi;
|
|
EEPROM::instance ().writeStationData (data);
|
|
sendEmptyReply (true);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::setName(const char* name)
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
strncpy (data.name, name, sizeof data.name);
|
|
EEPROM::instance ().writeStationData (data);
|
|
sendEmptyReply (true);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::setCallSign(const char *callsign)
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
strncpy (data.callsign, callsign, sizeof data.callsign);
|
|
EEPROM::instance ().writeStationData (data);
|
|
sendEmptyReply (true);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::setBeam(uint8_t beam)
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
data.beam = beam;
|
|
EEPROM::instance ().writeStationData (data);
|
|
sendEmptyReply (true);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::setLength(uint8_t len)
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
data.len = len;
|
|
EEPROM::instance ().writeStationData (data);
|
|
sendEmptyReply (true);
|
|
}
|
|
|
|
void
|
|
CommandProcessor::setVesselData(const char *s)
|
|
{
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
|
|
/*
|
|
* TODO: Add to/from CSV methods in StationData and use tokenization instead of sscanf()
|
|
*/
|
|
int items = sscanf (s, "%lu,%s,%s,%cu,%cu", &data.mmsi, data.name, data.callsign, &data.beam, &data.len);
|
|
if (items < 5)
|
|
sendEmptyReply (false);
|
|
else {
|
|
EEPROM::instance ().writeStationData (data);
|
|
sendEmptyReply (true);
|
|
}
|
|
}
|
|
|
|
void
|
|
CommandProcessor::setMode(const char *mode)
|
|
{
|
|
if (strcmp (mode, "dfu") == 0) {
|
|
FLASH_Unlock ();
|
|
FLASH_Status status = FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
|
|
if (status != FLASH_COMPLETE) {
|
|
sendError ("Unable to unlock flash");
|
|
return;
|
|
}
|
|
|
|
FLASH_ErasePage (METADATA_ADDRESS);
|
|
status = FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
|
|
if (status != FLASH_COMPLETE) {
|
|
sendError ("Unable to erase metadata page");
|
|
return;
|
|
}
|
|
|
|
FLASH_Lock ();
|
|
FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
|
|
if (status != FLASH_COMPLETE) {
|
|
sendError ("Unable to lock flash");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* UART takes a while to send reply, so unless we add considerable delay here, it won't make it before MCU reset
|
|
*/
|
|
//sendEmptyReply (true);
|
|
Event *e = EventPool::instance ().newEvent (RESET_EVENT);
|
|
EventQueue::instance ().push (e);
|
|
}
|
|
else if (strcmp (mode, "rx") == 0) {
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
data.flags |= STATION_RX_ONLY;
|
|
EEPROM::instance ().writeStationData (data);
|
|
sendEmptyReply (true);
|
|
}
|
|
else if (strcmp (mode, "trx") == 0) {
|
|
StationData data;
|
|
EEPROM::instance ().readStationData (data);
|
|
data.flags &= ~(STATION_RX_ONLY);
|
|
EEPROM::instance ().writeStationData (data);
|
|
sendEmptyReply (true);
|
|
}
|
|
else
|
|
sendError ("Unrecognized mode");
|
|
}
|
|
|