├── examples ├── Other │ ├── mDNSExample │ │ ├── .esp32.test.only │ │ ├── .esp8266.test.only │ │ └── mDNSExample.mlpz │ └── MLPExample │ │ ├── MLPExample.mlpz │ │ └── MLPExample.ino ├── CommandHandler │ ├── WiFiTCPBlink │ │ ├── .esp32.test.only │ │ ├── .esp8266.test.only │ │ └── WiFiTCPBlink.mlpz │ ├── ESP32BlueTooth │ │ ├── .esp32.test.only │ │ ├── ESP32BlueTooth.mlpz │ │ └── ESP32BlueTooth.ino │ ├── HandleUDPCommands │ │ ├── .esp8266.test.only │ │ └── HandleUDPCommands.mlpz │ ├── ENC28J60UDPCommandHandler │ │ ├── .uno.test.only │ │ ├── .mega2560.test.only │ │ └── ENC28J60UDPCommandHandler.mlpz │ ├── MultiSourceCommandHandler │ │ ├── .mega2560.test.only │ │ └── MultiSourceCommandHandler.ino │ └── HandleSerialCommands │ │ └── HandleSerialCommands.mlpz ├── InterfacePanel │ ├── ServoControl │ │ ├── .esp32.test.skip │ │ ├── .samd.test.skip │ │ ├── .metro_m4.test.skip │ │ ├── ServoControl.mlpz │ │ └── ServoControl.ino │ ├── SetParametersWithEEPROM │ │ ├── .uno.test.only │ │ ├── .mega2560.test.only │ │ ├── SetParametersWithEEPROM.mlpz │ │ └── SetParametersWithEEPROM.ino │ ├── Blink2 │ │ └── Blink2.mlpz │ ├── Prompt │ │ ├── Prompt.mlpz │ │ └── Prompt.ino │ ├── ColorTest │ │ ├── ColorTest.mlpz │ │ └── ColorTest.ino │ ├── MoveMotor │ │ ├── MoveMotor.mlpz │ │ └── MoveMotor.ino │ ├── SendToMLP │ │ ├── SendToMLP.mlpz │ │ └── SendToMLP.ino │ ├── ValueList │ │ ├── ValueList.mlpz │ │ └── ValueList.ino │ ├── RadioButtons │ │ ├── RadioButtons.mlpz │ │ └── RadioButtons.ino │ ├── SetParameters │ │ ├── SetParameters.mlpz │ │ └── SetParameters.ino │ ├── MultiplePlots │ │ ├── Multiple plots.mlpz │ │ └── MultiplePlots.ino │ ├── RequestAMatrix │ │ └── RequestAMatrix.mlpz │ ├── SliderSnapBack │ │ ├── SliderSnapBack.mlpz │ │ └── SliderSnapBack.ino │ ├── BlinkPictureBox │ │ ├── BlinkPictureBox.mlpz │ │ └── BlinkPictureBox.ino │ ├── HandlingStrings │ │ ├── HandlingStrings.mlpz │ │ └── HandlingStrings.ino │ ├── TurnLEDOffAndOn │ │ ├── TurnLEDOffAndOn.mlpz │ │ └── TurnLEDOffAndOn.ino │ ├── SendCheckboxState │ │ ├── SendCheckboxState.mlpz │ │ └── SendCheckboxState.ino │ ├── ConfigurableOutputPin │ │ ├── ConfigurableOutputPin.mlpz │ │ └── ConfigurableOutputPin.ino │ ├── IsMegunoLinkConnected │ │ ├── IsMegunoLinkConnected.mlpz │ │ └── IsMegunoLinkConnected.ino │ ├── RequestSingleParameter │ │ └── RequestSingleParameter.mlpz │ ├── UpdatingInterfaceFromArduino │ │ └── UpdatingInterfaceFromArduino.mlpz │ └── SingleMessageMultipleParameters │ │ ├── SingleMessageMultipleParameters.mlpz │ │ └── SingleMessageMultipleParameters.ino ├── TestReport │ └── TestDeviceVoltage │ │ ├── .uno.test.only │ │ ├── .mega2560.test.only │ │ └── TestDeviceVoltage.mlpz ├── TimePlot │ ├── ENC28J60UDPPlotting │ │ ├── .uno.test.only │ │ ├── .mega2560.test.only │ │ ├── ENC28J60UDPPlotting.mlpz │ │ └── ENC28J60UDPPlotting.ino │ ├── ESP32TCPWirelessPlotting │ │ ├── .esp32.test.only │ │ └── ESP32TCPWirelessPlotting.mlpz │ ├── ESP8266TCPClientPlotting │ │ ├── .esp8266.test.only │ │ ├── TCP Server.mlpz │ │ └── ESP8266TCPClientPlotting.ino │ ├── ESP8266UDPWirelessPlotting │ │ ├── .esp8266.test.only │ │ └── ESP8266UDPWirelessPlotting.mlpz │ ├── ESPTCPServerWirelessPlotting │ │ ├── .esp32.test.only │ │ ├── .esp8266.test.only │ │ └── ESPTCPServerWirelessPlotting.mlpz │ ├── ESPTCPServerPlottingWithCommands │ │ ├── .esp32.test.only │ │ ├── .esp8266.test.only │ │ └── ESPTCPServerPlottingWithCommands.mlpz │ ├── Sinewave │ │ ├── Sinewave.mlpz │ │ └── Sinewave.ino │ ├── LightSensor │ │ ├── LightSensor.mlpz │ │ └── LightSensor.ino │ ├── TwoAxisPlot │ │ ├── TwoAxisPlot.mlpz │ │ └── TwoAxisPlot.ino │ ├── MultiplePlots │ │ ├── MultiplePlots.mlpz │ │ └── MultiplePlots.ino │ ├── PlotAnalogValue │ │ ├── PlotAnalogValue.mlpz │ │ └── PlotAnalogValue.ino │ ├── RainbowSinewave │ │ ├── RainbowSinewave.mlpz │ │ └── RainbowSinewave.ino │ ├── EthernetUDPPlotting │ │ ├── EthernetUDPPlotting.mlpz │ │ └── EthernetUDPPlotting.ino │ └── PlotAnalogValueWithTime │ │ └── PlotAnalogValueWithTime.mlpz ├── XYPlot │ ├── Lissajou │ │ ├── Lissajou.mlpz │ │ └── Lissajou.ino │ └── PlotAnalogValue │ │ ├── PlotAnalogValue.mlpz │ │ └── PlotAnalogValue.ino ├── Getting Started │ ├── Blink2 │ │ └── Blink2.mlpz │ ├── Sinewave │ │ └── Sinewave.mlpz │ ├── SendToTable │ │ ├── SendToTable.mlpz │ │ └── SendToTable.ino │ ├── DeviceFileTransfer │ │ └── Device file transfer.mlpz │ ├── SendCommandSequence │ │ ├── Send command sequence.mlpz │ │ └── SendCommandSequence.ino │ ├── XYPlotButtonBounce │ │ ├── XY plot button bounce.mlpz │ │ └── XYPlotButtonBounce.ino │ └── UpdatingInterfaceFromArduino │ │ └── UpdatingInterfaceFromArduino.mlpz ├── Table │ ├── SendToTable │ │ ├── SendToTable.mlpz │ │ └── SendToTable.ino │ └── ReportStartTime │ │ ├── Report start time.mlpz │ │ └── ReportStartTime.ino ├── RecordTable │ ├── SendArray │ │ ├── SendArray.mlpz │ │ └── SendArray.ino │ ├── SendToCell │ │ ├── SendToCell.mlpz │ │ └── SendToCell.ino │ └── BasicRecordTable │ │ ├── BasicRecordTable.mlpz │ │ └── BasicRecordTable.ino ├── ScheduledReport │ ├── ScheduledReport.mlpz │ └── ScheduledReport.ino ├── ExponentialFilter │ ├── ExponentialFilter.mlpz │ └── ExponentialFilter.ino ├── MessageLogger │ ├── LogToFiles │ │ ├── LogToFiles.mlpz │ │ └── LogToFiles.ino │ ├── SendCSVData │ │ ├── SendCSVData.mlpz │ │ └── SendCSVData.ino │ └── MultipleCSVLogFiles │ │ ├── MultipleCSVLogFiles.mlpz │ │ └── MultipleCSVLogFiles.ino ├── Mapping │ └── PlotCoordinates │ │ ├── PlotCoordinates.mlpz │ │ └── PlotCoordinates.ino ├── MessageMonitor │ ├── SendCSVData │ │ ├── SendCSVData.mlpz │ │ └── SendCSVData.ino │ └── AdjustableSinewave │ │ └── AdjustableSinewave.mlpz ├── Services │ └── SpeechAndAudio │ │ ├── SpeechAndAudio.mlpz │ │ └── SpeechAndAudio.ino ├── InitializingSettings │ ├── InitializingSettings.mlpz │ └── InitializingSettings.ino ├── MessageMonkey │ └── MoveToPositions │ │ └── Move to positions.mlpz ├── ExponentialFilterExplorer │ ├── ExponentialFilterExplorer.mlpz │ └── ExponentialFilterExplorer.ino └── CircularBuffer │ └── CircularBuffer.ino ├── src ├── BlockParser.h ├── utility │ ├── Pushover.cpp │ ├── CRC.h │ ├── Report.h │ ├── Report.cpp │ ├── Audio.cpp │ ├── Table.cpp │ ├── Monkey.cpp │ ├── Map.h │ ├── Monkey.h │ ├── Audio.h │ ├── PlotFormat.h │ ├── CRC.cpp │ ├── TCPConnection.h │ ├── CommandParameter.h │ ├── StreamParser.h │ ├── RecordTable.cpp │ ├── Map.cpp │ ├── XYPlot.cpp │ ├── MegunoLinkProtocol.h │ ├── Pushover.h │ ├── TestReport.cpp │ ├── Message.h │ ├── DeviceFileTransfer.h │ ├── StreamParser.cpp │ ├── Message.cpp │ ├── CommandParameter.cpp │ └── TestReport.h ├── CommandModule.cpp ├── NetworkDestination.h ├── TcpManager.h ├── MegunoLink.h ├── EspTicker.cpp ├── BlockParser.cpp ├── CommandDispatcher.h ├── DataStore.h ├── CommandProcessor.h ├── CommandModule.h ├── FixedStringBuffer.cpp ├── UdpResponseStream.h ├── MessageHeaders.h ├── DeviceAddress.h ├── MegunoLinkNetwork.h ├── DeviceAddress.cpp ├── MLPMsgBuffer.cpp ├── EspTicker.h ├── UdpCommandHandler.h ├── UdpResponseStream.cpp ├── PrintBuffer.h ├── TCPCommandHandler.h ├── CommandHandler.h ├── UdpParser.h ├── MegunoLinkNetwork.cpp ├── UdpManager.h ├── UdpParser.cpp ├── ArduinoTimer.cpp ├── MLPMsgBuffer.h ├── ArduinoTimer.h ├── Formatting.h ├── Filter.h ├── MegunoLinkBufferWrapper.h ├── UdpManager.cpp ├── FixedStringBuffer.h ├── DataStore.cpp └── EEPROMStore.h ├── MegunoLink.vcxitems.user ├── library.properties ├── MLPLib.props ├── library.json ├── .github └── workflows │ └── githubci.yml ├── History.md ├── README.md └── keywords.txt /examples/Other/mDNSExample/.esp32.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/Other/mDNSExample/.esp8266.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/CommandHandler/WiFiTCPBlink/.esp32.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/InterfacePanel/ServoControl/.esp32.test.skip: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/InterfacePanel/ServoControl/.samd.test.skip: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/TestReport/TestDeviceVoltage/.uno.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/TimePlot/ENC28J60UDPPlotting/.uno.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/CommandHandler/ESP32BlueTooth/.esp32.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/CommandHandler/WiFiTCPBlink/.esp8266.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/InterfacePanel/ServoControl/.metro_m4.test.skip: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/TestReport/TestDeviceVoltage/.mega2560.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/TimePlot/ENC28J60UDPPlotting/.mega2560.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/CommandHandler/HandleUDPCommands/.esp8266.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/InterfacePanel/SetParametersWithEEPROM/.uno.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/TimePlot/ESP32TCPWirelessPlotting/.esp32.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/TimePlot/ESP8266TCPClientPlotting/.esp8266.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/TimePlot/ESP8266UDPWirelessPlotting/.esp8266.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/TimePlot/ESPTCPServerWirelessPlotting/.esp32.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/CommandHandler/ENC28J60UDPCommandHandler/.uno.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/InterfacePanel/SetParametersWithEEPROM/.mega2560.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/TimePlot/ESPTCPServerPlottingWithCommands/.esp32.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/TimePlot/ESPTCPServerWirelessPlotting/.esp8266.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/CommandHandler/ENC28J60UDPCommandHandler/.mega2560.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/CommandHandler/MultiSourceCommandHandler/.mega2560.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/TimePlot/ESPTCPServerPlottingWithCommands/.esp8266.test.only: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/XYPlot/Lissajou/Lissajou.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/XYPlot/Lissajou/Lissajou.mlpz -------------------------------------------------------------------------------- /examples/Other/MLPExample/MLPExample.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Other/MLPExample/MLPExample.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/Sinewave/Sinewave.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/Sinewave/Sinewave.mlpz -------------------------------------------------------------------------------- /examples/Getting Started/Blink2/Blink2.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Getting Started/Blink2/Blink2.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/Blink2/Blink2.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/Blink2/Blink2.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/Prompt/Prompt.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/Prompt/Prompt.mlpz -------------------------------------------------------------------------------- /examples/Other/mDNSExample/mDNSExample.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Other/mDNSExample/mDNSExample.mlpz -------------------------------------------------------------------------------- /examples/Table/SendToTable/SendToTable.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Table/SendToTable/SendToTable.mlpz -------------------------------------------------------------------------------- /examples/RecordTable/SendArray/SendArray.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/RecordTable/SendArray/SendArray.mlpz -------------------------------------------------------------------------------- /examples/ScheduledReport/ScheduledReport.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/ScheduledReport/ScheduledReport.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/LightSensor/LightSensor.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/LightSensor/LightSensor.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/TwoAxisPlot/TwoAxisPlot.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/TwoAxisPlot/TwoAxisPlot.mlpz -------------------------------------------------------------------------------- /examples/ExponentialFilter/ExponentialFilter.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/ExponentialFilter/ExponentialFilter.mlpz -------------------------------------------------------------------------------- /examples/Getting Started/Sinewave/Sinewave.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Getting Started/Sinewave/Sinewave.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/ColorTest/ColorTest.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/ColorTest/ColorTest.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/MoveMotor/MoveMotor.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/MoveMotor/MoveMotor.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/SendToMLP/SendToMLP.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/SendToMLP/SendToMLP.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/ValueList/ValueList.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/ValueList/ValueList.mlpz -------------------------------------------------------------------------------- /examples/MessageLogger/LogToFiles/LogToFiles.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/MessageLogger/LogToFiles/LogToFiles.mlpz -------------------------------------------------------------------------------- /examples/RecordTable/SendToCell/SendToCell.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/RecordTable/SendToCell/SendToCell.mlpz -------------------------------------------------------------------------------- /examples/MessageLogger/SendCSVData/SendCSVData.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/MessageLogger/SendCSVData/SendCSVData.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/MultiplePlots/MultiplePlots.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/MultiplePlots/MultiplePlots.mlpz -------------------------------------------------------------------------------- /src/BlockParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class BlockParser 4 | { 5 | protected: 6 | bool FindCommand(char *&rpchBuffer, int &rszLength); 7 | 8 | }; -------------------------------------------------------------------------------- /examples/CommandHandler/WiFiTCPBlink/WiFiTCPBlink.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/CommandHandler/WiFiTCPBlink/WiFiTCPBlink.mlpz -------------------------------------------------------------------------------- /examples/Getting Started/SendToTable/SendToTable.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Getting Started/SendToTable/SendToTable.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/RadioButtons/RadioButtons.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/RadioButtons/RadioButtons.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/ServoControl/ServoControl.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/ServoControl/ServoControl.mlpz -------------------------------------------------------------------------------- /examples/Mapping/PlotCoordinates/PlotCoordinates.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Mapping/PlotCoordinates/PlotCoordinates.mlpz -------------------------------------------------------------------------------- /examples/MessageMonitor/SendCSVData/SendCSVData.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/MessageMonitor/SendCSVData/SendCSVData.mlpz -------------------------------------------------------------------------------- /examples/Services/SpeechAndAudio/SpeechAndAudio.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Services/SpeechAndAudio/SpeechAndAudio.mlpz -------------------------------------------------------------------------------- /examples/Table/ReportStartTime/Report start time.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Table/ReportStartTime/Report start time.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/PlotAnalogValue/PlotAnalogValue.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/PlotAnalogValue/PlotAnalogValue.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/RainbowSinewave/RainbowSinewave.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/RainbowSinewave/RainbowSinewave.mlpz -------------------------------------------------------------------------------- /examples/XYPlot/PlotAnalogValue/PlotAnalogValue.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/XYPlot/PlotAnalogValue/PlotAnalogValue.mlpz -------------------------------------------------------------------------------- /examples/InitializingSettings/InitializingSettings.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InitializingSettings/InitializingSettings.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/SetParameters/SetParameters.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/SetParameters/SetParameters.mlpz -------------------------------------------------------------------------------- /examples/CommandHandler/ESP32BlueTooth/ESP32BlueTooth.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/CommandHandler/ESP32BlueTooth/ESP32BlueTooth.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/MultiplePlots/Multiple plots.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/MultiplePlots/Multiple plots.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/RequestAMatrix/RequestAMatrix.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/RequestAMatrix/RequestAMatrix.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/SliderSnapBack/SliderSnapBack.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/SliderSnapBack/SliderSnapBack.mlpz -------------------------------------------------------------------------------- /examples/RecordTable/BasicRecordTable/BasicRecordTable.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/RecordTable/BasicRecordTable/BasicRecordTable.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/ESP8266TCPClientPlotting/TCP Server.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/ESP8266TCPClientPlotting/TCP Server.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/BlinkPictureBox/BlinkPictureBox.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/BlinkPictureBox/BlinkPictureBox.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/HandlingStrings/HandlingStrings.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/HandlingStrings/HandlingStrings.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/TurnLEDOffAndOn/TurnLEDOffAndOn.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/TurnLEDOffAndOn/TurnLEDOffAndOn.mlpz -------------------------------------------------------------------------------- /examples/MessageMonkey/MoveToPositions/Move to positions.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/MessageMonkey/MoveToPositions/Move to positions.mlpz -------------------------------------------------------------------------------- /examples/TestReport/TestDeviceVoltage/TestDeviceVoltage.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TestReport/TestDeviceVoltage/TestDeviceVoltage.mlpz -------------------------------------------------------------------------------- /examples/CommandHandler/HandleUDPCommands/HandleUDPCommands.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/CommandHandler/HandleUDPCommands/HandleUDPCommands.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/SendCheckboxState/SendCheckboxState.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/SendCheckboxState/SendCheckboxState.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/ENC28J60UDPPlotting/ENC28J60UDPPlotting.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/ENC28J60UDPPlotting/ENC28J60UDPPlotting.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/EthernetUDPPlotting/EthernetUDPPlotting.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/EthernetUDPPlotting/EthernetUDPPlotting.mlpz -------------------------------------------------------------------------------- /examples/ExponentialFilterExplorer/ExponentialFilterExplorer.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/ExponentialFilterExplorer/ExponentialFilterExplorer.mlpz -------------------------------------------------------------------------------- /examples/MessageMonitor/AdjustableSinewave/AdjustableSinewave.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/MessageMonitor/AdjustableSinewave/AdjustableSinewave.mlpz -------------------------------------------------------------------------------- /src/utility/Pushover.cpp: -------------------------------------------------------------------------------- 1 | #include "Pushover.h" 2 | 3 | Pushover::Pushover(Print& rDestination /*= Serial*/) 4 | : MegunoLinkProtocol(F("PSH"), rDestination) 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /examples/Getting Started/DeviceFileTransfer/Device file transfer.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Getting Started/DeviceFileTransfer/Device file transfer.mlpz -------------------------------------------------------------------------------- /examples/MessageLogger/MultipleCSVLogFiles/MultipleCSVLogFiles.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/MessageLogger/MultipleCSVLogFiles/MultipleCSVLogFiles.mlpz -------------------------------------------------------------------------------- /examples/CommandHandler/HandleSerialCommands/HandleSerialCommands.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/CommandHandler/HandleSerialCommands/HandleSerialCommands.mlpz -------------------------------------------------------------------------------- /examples/Getting Started/SendCommandSequence/Send command sequence.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Getting Started/SendCommandSequence/Send command sequence.mlpz -------------------------------------------------------------------------------- /examples/Getting Started/XYPlotButtonBounce/XY plot button bounce.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Getting Started/XYPlotButtonBounce/XY plot button bounce.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/PlotAnalogValueWithTime/PlotAnalogValueWithTime.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/PlotAnalogValueWithTime/PlotAnalogValueWithTime.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/ConfigurableOutputPin/ConfigurableOutputPin.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/ConfigurableOutputPin/ConfigurableOutputPin.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/IsMegunoLinkConnected/IsMegunoLinkConnected.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/IsMegunoLinkConnected/IsMegunoLinkConnected.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/RequestSingleParameter/RequestSingleParameter.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/RequestSingleParameter/RequestSingleParameter.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/ESP32TCPWirelessPlotting/ESP32TCPWirelessPlotting.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/ESP32TCPWirelessPlotting/ESP32TCPWirelessPlotting.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/SetParametersWithEEPROM/SetParametersWithEEPROM.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/SetParametersWithEEPROM/SetParametersWithEEPROM.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/ESP8266UDPWirelessPlotting/ESP8266UDPWirelessPlotting.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/ESP8266UDPWirelessPlotting/ESP8266UDPWirelessPlotting.mlpz -------------------------------------------------------------------------------- /src/utility/CRC.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | uint16_t CalculateChecksum(uint8_t const* pData, uint16_t uLength, uint16_t uSeed = 0xffff); 4 | uint16_t CalculateChecksum(uint8_t uData, uint16_t uSeed = 0xffff); 5 | -------------------------------------------------------------------------------- /examples/CommandHandler/ENC28J60UDPCommandHandler/ENC28J60UDPCommandHandler.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/CommandHandler/ENC28J60UDPCommandHandler/ENC28J60UDPCommandHandler.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/ESPTCPServerWirelessPlotting/ESPTCPServerWirelessPlotting.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/ESPTCPServerWirelessPlotting/ESPTCPServerWirelessPlotting.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/UpdatingInterfaceFromArduino/UpdatingInterfaceFromArduino.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/UpdatingInterfaceFromArduino/UpdatingInterfaceFromArduino.mlpz -------------------------------------------------------------------------------- /examples/Getting Started/UpdatingInterfaceFromArduino/UpdatingInterfaceFromArduino.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/Getting Started/UpdatingInterfaceFromArduino/UpdatingInterfaceFromArduino.mlpz -------------------------------------------------------------------------------- /examples/TimePlot/ESPTCPServerPlottingWithCommands/ESPTCPServerPlottingWithCommands.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/TimePlot/ESPTCPServerPlottingWithCommands/ESPTCPServerPlottingWithCommands.mlpz -------------------------------------------------------------------------------- /examples/InterfacePanel/SingleMessageMultipleParameters/SingleMessageMultipleParameters.mlpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Megunolink/MLP/HEAD/examples/InterfacePanel/SingleMessageMultipleParameters/SingleMessageMultipleParameters.mlpz -------------------------------------------------------------------------------- /src/CommandModule.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandModule.h" 2 | 3 | using namespace MLP; 4 | 5 | CommandModule::CommandModule(const __FlashStringHelper* pName) 6 | : Command((PGM_P)pName) 7 | { 8 | NextModule = nullptr; 9 | } 10 | -------------------------------------------------------------------------------- /MegunoLink.vcxitems.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /src/utility/Report.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MegunoLinkProtocol.h" 3 | 4 | class Report : public MegunoLinkProtocol 5 | { 6 | 7 | public: 8 | Report(Print& rDestination = Serial); 9 | 10 | void GenerateNow(); 11 | 12 | void EnablePeriodicReports(bool bEnable = true); 13 | 14 | }; -------------------------------------------------------------------------------- /src/NetworkDestination.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class INetworkDestination 6 | { 7 | public: 8 | virtual bool SendBlock(const char* pchData, size_t szLength, IPAddress ipDestination, uint16_t uPort = 0) = 0; 9 | }; 10 | 11 | class IStreamDestination 12 | { 13 | public: 14 | virtual bool SendBlock(const char* pchData, size_t szLength) = 0; 15 | }; -------------------------------------------------------------------------------- /examples/TimePlot/MultiplePlots/MultiplePlots.ino: -------------------------------------------------------------------------------- 1 | #include "MegunoLink.h" 2 | 3 | float x = 0; 4 | 5 | void setup() 6 | { 7 | Serial.begin(9600); 8 | } 9 | 10 | void loop() 11 | { 12 | TimePlot SinePlot("Sin"), CosinePlot("Cos"); 13 | 14 | SinePlot.SendData("Sine", sin(x)); 15 | CosinePlot.SendData("Cosine", cos(x)); 16 | x = x + 0.1; 17 | 18 | delay(100); 19 | } 20 | -------------------------------------------------------------------------------- /examples/InterfacePanel/MultiplePlots/MultiplePlots.ino: -------------------------------------------------------------------------------- 1 | #include "MegunoLink.h" 2 | 3 | float x = 0; 4 | 5 | void setup() 6 | { 7 | Serial.begin(9600); 8 | } 9 | 10 | void loop() 11 | { 12 | TimePlot SinePlot("Sin"), CosinePlot("Cos"); 13 | 14 | SinePlot.SendData("Sine", sin(x)); 15 | CosinePlot.SendData("Cosine", cos(x)); 16 | x = x + 0.1; 17 | 18 | delay(100); 19 | } 20 | -------------------------------------------------------------------------------- /src/TcpManager.h: -------------------------------------------------------------------------------- 1 | /* *********************************************************************** 2 | * TcpManager 3 | * Maintains Tcp connections 4 | * *********************************************************************** */ 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | class ITcpManager 11 | { 12 | public: 13 | virtual Client& GetConnection() = 0; 14 | }; -------------------------------------------------------------------------------- /src/utility/Report.cpp: -------------------------------------------------------------------------------- 1 | #include "Report.h" 2 | 3 | Report::Report(Print& rDestination) 4 | : MegunoLinkProtocol(F("REPORT"), rDestination) 5 | { 6 | } 7 | 8 | void Report::GenerateNow() 9 | { 10 | SendDataHeader(F("SAVE")); 11 | SendDataTail(); 12 | } 13 | 14 | void Report::EnablePeriodicReports(bool bEnable) 15 | { 16 | SendDataHeader(F("ENABLE")); 17 | m_rDestination.print(bEnable ? 'T' : 'F'); 18 | SendDataTail(); 19 | } 20 | -------------------------------------------------------------------------------- /src/MegunoLink.h: -------------------------------------------------------------------------------- 1 | #include "utility/InterfacePanel.h" 2 | #include "utility/Map.h" 3 | #include "utility/Message.h" 4 | #include "utility/Table.h" 5 | #include "utility/TimePlot.h" 6 | #include "utility/XYPlot.h" 7 | #include "utility/TestReport.h" 8 | #include "utility/Report.h" 9 | #include "utility/RecordTable.h" 10 | #include "utility/Audio.h" 11 | #include "utility/Pushover.h" 12 | #include "utility/Monkey.h" 13 | #include "utility/DeviceFileTransfer.h" -------------------------------------------------------------------------------- /src/utility/Audio.cpp: -------------------------------------------------------------------------------- 1 | #include "Audio.h" 2 | 3 | Audio::Audio(Print& rDestination) 4 | : MegunoLinkProtocol(F("AUDIO"), rDestination) 5 | { 6 | } 7 | 8 | void Audio::PlayAudioClip(const char* ClipId) 9 | { 10 | PlayClip(ClipId); 11 | } 12 | 13 | void Audio::PlayAudioClip(const __FlashStringHelper* ClipId) 14 | { 15 | PlayClip(ClipId); 16 | } 17 | 18 | void Audio::PlayAudioClip(const String& ClipId) 19 | { 20 | PlayClip(ClipId.c_str()); 21 | } 22 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=MegunoLink 2 | version=1.43 3 | author=Number Eight Innovation 4 | maintainer=Number Eight Innovation 5 | sentence=Library for storing data in the eeprom, processing serial messages and plotting data with MegunoLink. 6 | paragraph=Also includes handy timer and filtering tools. 7 | url=https://www.megunolink.com/documentation/arduino-library/ 8 | category=Communication 9 | architectures=* 10 | includes=MegunoLink.h,CommandHandler.h,ArduinoTimer.h 11 | -------------------------------------------------------------------------------- /src/EspTicker.cpp: -------------------------------------------------------------------------------- 1 | #include "EspTicker.h" 2 | 3 | #if defined(ARDUINO_ARCH_ESP32) 4 | 5 | void EspTicker::once(float fSeconds, callback_function_t handler) 6 | { 7 | m_SourceTicker.once(fSeconds, OnTick, this); 8 | } 9 | 10 | void EspTicker::OnTick(EspTicker* pTimer) 11 | { 12 | if (pTimer != nullptr && pTimer->m_Handler != nullptr) 13 | { 14 | pTimer->m_Handler(); 15 | } 16 | } 17 | 18 | void EspTicker::detach() 19 | { 20 | m_SourceTicker.detach(); 21 | } 22 | #endif 23 | -------------------------------------------------------------------------------- /src/BlockParser.cpp: -------------------------------------------------------------------------------- 1 | #include "BlockParser.h" 2 | 3 | bool BlockParser::FindCommand(char *&rpchBuffer, int &rnLength) 4 | { 5 | if (rnLength <= 2 || *rpchBuffer != '!') 6 | { 7 | return false; 8 | } 9 | ++rpchBuffer; 10 | --rnLength; 11 | 12 | char *pchEnd = rpchBuffer; 13 | int nLength = 0; 14 | while (nLength < rnLength && *pchEnd != '\r' && *pchEnd != '\n') 15 | { 16 | ++pchEnd; 17 | ++nLength; 18 | } 19 | 20 | rnLength = nLength; 21 | rpchBuffer[rnLength] = '\0'; 22 | return rnLength > 0; 23 | } -------------------------------------------------------------------------------- /src/CommandDispatcher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CommandDispatcherBase.h" 4 | 5 | template class CommandDispatcher : public MLP::CommandDispatcherBase 6 | { 7 | // Array of commands we can match & dispatch. 8 | MLP::CommandCallback m_Commands[MAX_COMMANDS]; 9 | 10 | // Array of variables we can match & set/print 11 | MLP::VariableMap m_Variables[MAX_VARIABLES]; 12 | 13 | 14 | public: 15 | CommandDispatcher() : CommandDispatcherBase(m_Commands, MAX_COMMANDS, m_Variables, MAX_VARIABLES) 16 | { 17 | } 18 | }; -------------------------------------------------------------------------------- /src/DataStore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "MessageHeaders.h" 4 | #include "DeviceAddress.h" 5 | 6 | class DataStore 7 | { 8 | static uint8_t s_uNextId; 9 | 10 | public: 11 | static void Send(uint32_t uSenderId, byte DataContext, byte DataChannel, void const * pData, uint8_t uDataSize); 12 | 13 | private: 14 | static uint16_t CalculateChecksum(CMessageHeader const &rHeader, uint8_t const * pData, uint8_t uDataSize); 15 | static void WriteHex(const void *pData, uint8_t uLength); 16 | static void WriteHex(uint8_t uData); 17 | 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /src/utility/Table.cpp: -------------------------------------------------------------------------------- 1 | #include "Table.h" 2 | 3 | Table::Table(Print& rDestination /*= Serial*/) 4 | : MegunoLinkProtocol(F("PT"), rDestination) 5 | { 6 | 7 | } 8 | 9 | Table::Table(const char *Channel, Print &rDestination /*= Serial*/) 10 | : MegunoLinkProtocol(F("PT"), Channel, rDestination) 11 | { 12 | 13 | } 14 | 15 | Table::Table(const __FlashStringHelper *Channel, Print &rDestination /*= Serial*/) 16 | : MegunoLinkProtocol(F("PT"), Channel, rDestination) 17 | { 18 | 19 | } 20 | 21 | void Table::ClearAllRows() 22 | { 23 | SendDataHeader(F("CLR")); 24 | SendDataTail(); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/utility/Monkey.cpp: -------------------------------------------------------------------------------- 1 | #include "Monkey.h" 2 | 3 | Monkey::Monkey(Print& rDestination) 4 | : MegunoLinkProtocol(F("Mky"), rDestination) 5 | { 6 | 7 | } 8 | 9 | Monkey::Monkey(const char *channelName /*= NULL*/, Print &rDestination) 10 | : MegunoLinkProtocol(F("Mky"), channelName, rDestination) 11 | { 12 | 13 | } 14 | 15 | Monkey::Monkey(const __FlashStringHelper* channelName, Print& rDestination) 16 | : MegunoLinkProtocol(F("Mky"), channelName, rDestination) 17 | { 18 | 19 | } 20 | 21 | void Monkey::ClearTriggers() 22 | { 23 | SendDataHeader(F("CLR")); 24 | SendDataTail(); 25 | } 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/CommandProcessor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "CommandDispatcher.h" 4 | #include "utility/StreamParser.h" 5 | 6 | template class CommandProcessor : public MLP::StreamParser 7 | { 8 | // Buffer for data received. 9 | char m_achBuffer[CP_SERIAL_BUFFER_SIZE]; 10 | 11 | public: 12 | CommandProcessor(MLP::CommandDispatcherBase &rCommandHandler, Stream &rSourceStream = Serial, char chStartOfMessage = '!', char chEndOfMessage = '\r') 13 | : StreamParser(rCommandHandler, m_achBuffer, CP_SERIAL_BUFFER_SIZE, rSourceStream, chStartOfMessage, chEndOfMessage) 14 | { 15 | } 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /src/CommandModule.h: -------------------------------------------------------------------------------- 1 | /* ***************************************************************** 2 | * Extension point for command dispatcher to implement modules with 3 | * sets of commands that can be linked to command handling. 4 | * ***************************************************************** */ 5 | #pragma once 6 | 7 | #include 8 | #include "utility/CommandParameter.h" 9 | 10 | namespace MLP 11 | { 12 | class CommandModule 13 | { 14 | public: 15 | CommandModule(const __FlashStringHelper* pName); 16 | PGM_P const Command; 17 | CommandModule* NextModule; 18 | 19 | virtual void DispatchCommand(CommandParameter& p) = 0; 20 | }; 21 | 22 | } -------------------------------------------------------------------------------- /src/FixedStringBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "FixedStringBuffer.h" 2 | 3 | FixedStringPrint::FixedStringPrint(char* pchBuffer, size_t szBuffer) 4 | { 5 | m_pchBuffer = pchBuffer; 6 | m_szBuffer = szBuffer; 7 | begin(); 8 | } 9 | 10 | void FixedStringPrint::begin() 11 | { 12 | m_pchNext = m_pchBuffer; 13 | if (m_szBuffer > 0) 14 | { 15 | *m_pchNext = '\0'; 16 | } 17 | m_bBufferFlow = false; 18 | } 19 | 20 | size_t FixedStringPrint::write(uint8_t uValue) 21 | { 22 | if ((m_pchNext + 1) < (m_pchBuffer + m_szBuffer)) 23 | { 24 | *m_pchNext++ = uValue; 25 | *m_pchNext = '\0'; 26 | return 1; 27 | } 28 | 29 | m_bBufferFlow = true; 30 | return 0; 31 | } -------------------------------------------------------------------------------- /src/UdpResponseStream.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "MLPMsgBuffer.h" 4 | 5 | namespace MLP 6 | { 7 | class UdpResponseStream : public MLPMsgDestination 8 | { 9 | private: 10 | 11 | UDP & m_rConnection; 12 | bool m_bStartedPacket; 13 | 14 | IPAddress m_ipDestinationAddress; 15 | uint16_t m_uDestinationPort; 16 | 17 | const static int BufferSize = 128; 18 | char m_achBuffer[BufferSize]; 19 | 20 | public: 21 | UdpResponseStream(UDP& rConnection, IPAddress ipDestinationAddress, uint16_t uDestinationPort); 22 | 23 | virtual void flush() override; 24 | 25 | void EndTransmission(); 26 | }; 27 | 28 | } // namespace MLP 29 | -------------------------------------------------------------------------------- /src/MessageHeaders.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct CMessageHeader 4 | { 5 | enum EType 6 | { 7 | TYPE_Command = '!', 8 | TYPE_Reply = '@' 9 | } __attribute__((__packed__)); 10 | 11 | enum EContext 12 | { 13 | CTX_DataTransport = 'A', 14 | } __attribute__((__packed__)); 15 | 16 | enum EConstants 17 | { 18 | ChecksumSeed = 0x50 19 | } __attribute__((__packed__)); 20 | 21 | uint16_t Checksum; // entire message content, excluding checksum bytes. Must be at start. 22 | EType Type; 23 | uint8_t Id; 24 | uint32_t SenderAddress; 25 | uint16_t TimeStamp; // For debugging. 26 | EContext Context; 27 | uint16_t Command; 28 | } __attribute__((__packed__)); 29 | 30 | -------------------------------------------------------------------------------- /src/utility/Map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MegunoLinkProtocol.h" 3 | 4 | class Map : public MegunoLinkProtocol 5 | { 6 | public: 7 | Map(Print &rDestination = Serial); 8 | Map(const __FlashStringHelper* channelName, Print& rDestination = Serial); 9 | Map(const char* channelName, Print& rDestination = Serial); 10 | 11 | 12 | void SendData(const char *Placename, const char *Latitude, const char *Longitude); 13 | void SendData(const __FlashStringHelper *Placename, const char *Latitude, const char *Longitude); 14 | 15 | void SendData(const char *Placename, float Latitude, float Longitude); 16 | void SendData(const __FlashStringHelper *Placename, float Latitude, float Longitude); 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /src/DeviceAddress.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* ----------------------------------------------------------------------------- 4 | * Node Address 5 | * Use MegunoLink Pro's Id Writer to set this address. Address is 2 alpha characters 6 | * followed by up to 5 numeric digits 7 | * Address: 10 8 | * Format: Melvyn alpha, little-endian 9 | * ----------------------------------------------------------------------------- */ 10 | #define DEFAULT_DEVICE_ID_ADDRESS ((uint8_t*)10) 11 | 12 | // Broadcast address for site 0 relays. 13 | const uint32_t BroadcastRelayAddress = 0xffffff8f; 14 | 15 | uint32_t GetDeviceAddress(uint8_t const * pLocation = DEFAULT_DEVICE_ID_ADDRESS); 16 | void WriteMelvynFormatId(uint32_t uId); 17 | -------------------------------------------------------------------------------- /MLPLib.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | $(MSBuildThisFileDirectory) 12 | 13 | 14 | 15 | 16 | 17 | $(MSBuildThisFileDirectory);%(AdditionalIncludeDirectories) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/Other/MLPExample/MLPExample.ino: -------------------------------------------------------------------------------- 1 | #include "MegunoLink.h" 2 | 3 | XYPlot xyplot("ChannelName"); 4 | TimePlot timeplot("ChannelName"); 5 | Table table; 6 | 7 | float test = 65.987; 8 | void setup() 9 | { 10 | // put your setup code here, to run once: 11 | Serial.begin(9600); 12 | 13 | timeplot.SetTitle("hello"); 14 | timeplot.SetXLabel("test"); 15 | 16 | } 17 | 18 | void loop() 19 | { 20 | int DataValue = analogRead(0); 21 | 22 | // put your main code here, to run repeatedly: 23 | timeplot.SendData("SeriesName",test,"r-2s2"); 24 | table.SendData("DataValue", DataValue, "this is a reading from analog channel 0"); 25 | xyplot.SendData("SeriesName",millis(),56.589,"b-2s2"); 26 | delay(1000); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/utility/Monkey.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MegunoLinkProtocol.h" 3 | 4 | class Monkey : public MegunoLinkProtocol 5 | { 6 | public: 7 | Monkey(Print& rDestination = Serial); 8 | Monkey(const char *channelName, Print &rDestination = Serial); 9 | Monkey(const __FlashStringHelper *channelName, Print &rDestination = Serial); 10 | 11 | void ClearTriggers(); 12 | 13 | template void ClearTrigger(TValue Name) 14 | { 15 | SendDataHeader(F("CLR")); 16 | m_rDestination.print(Name); 17 | SendDataTail(); 18 | } 19 | 20 | template void SetTrigger(TValue Name) 21 | { 22 | SendDataHeader(F("TRG")); 23 | m_rDestination.print(Name); 24 | SendDataTail(); 25 | } 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MegunoLink", 3 | "version": "1.43.0", 4 | "description": "Library for storing data in the eeprom, processing serial messages and plotting data with MegunoLink.", 5 | "keywords": "MegunoLink, command handler, filter, timer, circular buffer", 6 | "homepage": "https://www.MegunoLink.com", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/Megunolink/MLP.git" 10 | }, 11 | "authors": [ 12 | { 13 | "name": "Number Eight Innovation", 14 | "email": "support@MegunoLink.com", 15 | "url": "https://www.MegunoLink.com" 16 | } 17 | ], 18 | "license": "LGPL-3.0-only", 19 | "frameworks": "arduino", 20 | "platforms": "*", 21 | "build": { 22 | "libLDFMode": "deep" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/TimePlot/LightSensor/LightSensor.ino: -------------------------------------------------------------------------------- 1 | /* ************************************************************************ 2 | Plot Light Sensor Value 3 | This program demonstrates how MegunoLink's Time Plot visualiser can be used 4 | to plot the analog signal from a light dependent resistor. 5 | 6 | The example folder also contains a MegunoLink project with the Time Plot 7 | visulaiser ready to go. 8 | Visit: 9 | * http://www.MegunoLink.com to download MegunoLink. 10 | ************************************************************************ */ 11 | 12 | #include "MegunoLink.h" 13 | 14 | void setup() 15 | { 16 | Serial.begin(9600); 17 | Serial.println("Light sensor"); 18 | } 19 | 20 | void loop() 21 | { 22 | TimePlot LightPlot; 23 | LightPlot.SendData("Light", analogRead(0)); 24 | delay(100); 25 | } 26 | -------------------------------------------------------------------------------- /src/utility/Audio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MegunoLinkProtocol.h" 3 | 4 | class Audio : public MegunoLinkProtocol 5 | { 6 | public: 7 | Audio(Print& rDestination = Serial); 8 | 9 | template void Speak(TContent Content) 10 | { 11 | SendDataHeader(F("SPK")); 12 | m_rDestination.print(Content); 13 | SendDataTail(); 14 | } 15 | 16 | void PlayAudioClip(const char* ClipId); 17 | void PlayAudioClip(const __FlashStringHelper* ClipId); 18 | void PlayAudioClip(const String& ClipId); 19 | 20 | void Stop() 21 | { 22 | SendDataHeader(F("STP")); 23 | SendDataTail(); 24 | } 25 | 26 | private: 27 | template void PlayClip(const TId &ClipId) 28 | { 29 | SendDataHeader(F("PLA")); 30 | m_rDestination.print(ClipId); 31 | SendDataTail(); 32 | } 33 | }; -------------------------------------------------------------------------------- /src/MegunoLinkNetwork.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MegunoLink.h" 4 | #include "MLPMsgBuffer.h" 5 | #include "MegunoLinkBufferWrapper.h" 6 | 7 | #include "NetworkDestination.h" 8 | 9 | class MegunoLinkNetwork : public MLPMsgDestination, public MegunoLinkBufferWrapper 10 | { 11 | protected: 12 | INetworkDestination* m_pAddressedDestination; 13 | IStreamDestination* m_pStreamDestination; 14 | 15 | const static int BufferSize = 128; 16 | char m_achTransmitBuffer[BufferSize]; 17 | 18 | IPAddress m_ipDestination; 19 | uint16_t m_uDestinationPort; 20 | 21 | public: 22 | MegunoLinkNetwork(INetworkDestination& rDestination); 23 | MegunoLinkNetwork(IStreamDestination& rDestination); 24 | 25 | void SetDestination(IPAddress DestinationAddress, uint16_t uDestinationPort = 0); 26 | 27 | virtual void flush() override; 28 | }; -------------------------------------------------------------------------------- /examples/InterfacePanel/SliderSnapBack/SliderSnapBack.ino: -------------------------------------------------------------------------------- 1 | #include "MegunoLink.h" 2 | #include "CommandHandler.h" 3 | 4 | 5 | float SliderValue = 0; 6 | 7 | CommandHandler<> SerialCommandHandler; 8 | InterfacePanel MyPanel; 9 | 10 | 11 | void Cmd_SetSliderValue(CommandParameter &Parameters) 12 | { 13 | Serial.print("SliderVal:"); 14 | SliderValue=Parameters.NextParameterAsInteger(); 15 | Serial.println(SliderValue); 16 | MyPanel.SetNumber("MySlider", 0); //Return the slider to zero position 17 | } 18 | 19 | void setup() 20 | { 21 | Serial.begin(9600); 22 | Serial.println("Snap Back To Zero Slider Example"); 23 | Serial.println("-----------------------------"); 24 | 25 | SerialCommandHandler.AddCommand(F("SliderVal"), Cmd_SetSliderValue); 26 | 27 | } 28 | 29 | void loop() 30 | { 31 | SerialCommandHandler.Process(); 32 | } 33 | -------------------------------------------------------------------------------- /examples/InterfacePanel/TurnLEDOffAndOn/TurnLEDOffAndOn.ino: -------------------------------------------------------------------------------- 1 | #include "MegunoLink.h" 2 | #include "CommandHandler.h" 3 | 4 | #define LEDPIN 9 //Change this to the pin your LED is on. 5 | boolean LEDState = false; 6 | 7 | CommandHandler<> SerialCommandHandler; 8 | 9 | 10 | void Cmd_ToggleLED(CommandParameter &Parameters) 11 | { 12 | Serial.println("Got ToggleLED command."); 13 | LEDState = !LEDState; 14 | digitalWrite(LEDPIN,LEDState); 15 | } 16 | 17 | void setup() 18 | { 19 | Serial.begin(9600); 20 | Serial.println("MegunoLink Pro - Turning and LED on and off"); 21 | Serial.println("-----------------------------"); 22 | 23 | SerialCommandHandler.AddCommand(F("ToggleLED"), Cmd_ToggleLED); 24 | 25 | pinMode(LEDPIN,OUTPUT); 26 | digitalWrite(LEDPIN,LEDState); 27 | } 28 | 29 | void loop() 30 | { 31 | SerialCommandHandler.Process(); 32 | } 33 | -------------------------------------------------------------------------------- /src/DeviceAddress.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "DeviceAddress.h" 3 | 4 | #if defined(__AVR__) // Only AVR devices implement EEPROMs for Arduino. 5 | #include 6 | 7 | uint32_t GetDeviceAddress(uint8_t const * pLocation /*= DEFAULT_DEVICE_ID_ADDRESS*/) 8 | { 9 | uint32_t uId; 10 | eeprom_read_block(&uId, pLocation, sizeof(uId)); 11 | return uId; 12 | } 13 | #endif 14 | 15 | 16 | 17 | void WriteMelvynFormatId(uint32_t uId) 18 | { 19 | uint8_t u1 = ((uId & 0x03) << 3) | ((uId >> 13) & 0x07); 20 | uint8_t u2 = (uId >> 8) & 0x1f; 21 | char ch1 = (u1 == 0 || u1 > 26) ? ' ' : u1 - 1 + 'A'; 22 | char ch2 = (u2 == 0 || u2 > 26) ? ' ' : u2 - 1 + 'A'; 23 | uint16_t uNumericId = uId >> 16; 24 | 25 | Serial.print(ch1); 26 | Serial.print(ch2); 27 | Serial.print('-'); 28 | Serial.print(uNumericId); 29 | Serial.println(); 30 | } 31 | -------------------------------------------------------------------------------- /src/MLPMsgBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "MLPMsgBuffer.h" 2 | 3 | MLPMsgDestination::MLPMsgDestination(char* pchStart, int nLength) 4 | : m_pchStart(pchStart) 5 | , m_nBufferSize(nLength) 6 | { 7 | begin(); 8 | } 9 | 10 | void MLPMsgDestination::begin() 11 | { 12 | m_pchNext = m_pchStart; 13 | *m_pchNext = '\0'; 14 | } 15 | 16 | size_t MLPMsgDestination::write(uint8_t uValue) 17 | { 18 | char* pchEnd = m_pchStart + m_nBufferSize; 19 | if ((m_pchNext + 1) < pchEnd) 20 | { 21 | *m_pchNext++ = uValue; 22 | *m_pchNext = '\0'; 23 | 24 | bool bFull = m_pchNext == pchEnd - 1; 25 | if (uValue == '\n' || bFull) 26 | { 27 | flush(); 28 | begin(); 29 | } 30 | return 1; 31 | } 32 | 33 | return 0; 34 | } 35 | 36 | void MLPMsgDestination::EndTransmission() 37 | { 38 | if (length() > 0) 39 | { 40 | flush(); 41 | begin(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/Table/ReportStartTime/ReportStartTime.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program to send the micro start time to a MegunoLink Pro table. 3 | * Visit http://www.megunolink.com/documentation/table/ for more information. 4 | * ********************************************************************************************** */ 5 | 6 | #include "MegunoLink.h" // Helpful functions for communicating with MegunoLink Pro. 7 | 8 | // The table we are sending data to 9 | Table MyTable; 10 | 11 | void setup() 12 | { 13 | Serial.begin(9600); 14 | 15 | // short delay so the serial port has a chance to initialize 16 | delay(2000); 17 | 18 | // Tell MegunoLink to display the current time. 19 | MyTable.ShowCurrentTime("Last Start"); 20 | } 21 | 22 | void loop() 23 | { 24 | // do something interesting here 25 | } -------------------------------------------------------------------------------- /examples/InterfacePanel/SendCheckboxState/SendCheckboxState.ino: -------------------------------------------------------------------------------- 1 | #include "MegunoLink.h" 2 | #include "CommandHandler.h" 3 | 4 | #define LEDPIN 9 //Change this to the pin your LED is on. 5 | boolean LEDState = false; 6 | 7 | CommandHandler<> SerialCommandHandler; 8 | 9 | 10 | void Cmd_CheckBoxChanged(CommandParameter &Parameters) 11 | { 12 | Serial.println("Got checkbox command."); 13 | LEDState = Parameters.NextParameterAsInteger(); 14 | digitalWrite(LEDPIN, LEDState); 15 | } 16 | 17 | void setup() 18 | { 19 | Serial.begin(9600); 20 | Serial.println("MegunoLink Pro - Turning and LED on and off"); 21 | Serial.println("-----------------------------"); 22 | 23 | SerialCommandHandler.AddCommand(F("CheckBoxEvent"), Cmd_CheckBoxChanged); 24 | 25 | pinMode(LEDPIN, OUTPUT); 26 | digitalWrite(LEDPIN, LEDState); 27 | } 28 | 29 | void loop() 30 | { 31 | SerialCommandHandler.Process(); 32 | } -------------------------------------------------------------------------------- /examples/Mapping/PlotCoordinates/PlotCoordinates.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program which sends MegunoLink coordinates to plot on its Mapping visualiser. 3 | * 4 | * Visit http://www.megunolink.com/documentation/mapping/ for more information. 5 | * 6 | * ********************************************************************************************** */ 7 | #include "MegunoLink.h" 8 | 9 | Map MyMap; 10 | 11 | 12 | void setup() 13 | { 14 | Serial.begin(9600); 15 | } 16 | 17 | 18 | 19 | 20 | void loop() 21 | { 22 | 23 | // Sends the microcontroller coordinates for three sensor locations 24 | MyMap.SendData("Sensor Location 1",-37.785949,175.30081); 25 | MyMap.SendData("Sensor Location 2","-37.795949","175.30081"); 26 | MyMap.SendData("Sensor Location 3",-37.775949,175.30081); 27 | 28 | 29 | delay(1000); 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/EspTicker.h: -------------------------------------------------------------------------------- 1 | /* ****************************************************************** 2 | * A wrapper around the ESP32 timer implementation to support 3 | * function bindings. 4 | * ****************************************************************** */ 5 | #pragma once 6 | 7 | #if defined(ARDUINO_ARCH_ESP8266) 8 | #include "Ticker.h" 9 | 10 | class EspTicker : public Ticker 11 | { 12 | // That's it. Nothing special needed for the 8266 ticker. 13 | }; 14 | 15 | #elif defined(ARDUINO_ARCH_ESP32) 16 | 17 | #include "Ticker.h" 18 | #include 19 | 20 | 21 | class EspTicker 22 | { 23 | public: 24 | 25 | typedef std::function callback_function_t; 26 | 27 | void once(float fSeconds, callback_function_t handler); 28 | void detach(); 29 | private: 30 | Ticker m_SourceTicker; 31 | callback_function_t m_Handler = nullptr; 32 | 33 | static void OnTick(EspTicker* pTimer); 34 | 35 | }; 36 | 37 | 38 | 39 | #endif -------------------------------------------------------------------------------- /src/utility/PlotFormat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Plot.h" 4 | 5 | class LineFormat 6 | { 7 | public: 8 | LineFormat(Plot::LineStyle s, uint8_t uLineWidth) 9 | { 10 | Style = s; 11 | Width = uLineWidth; 12 | } 13 | 14 | Plot::LineStyle Style; 15 | uint8_t Width; 16 | }; 17 | 18 | 19 | class MarkerFormat 20 | { 21 | public: 22 | MarkerFormat(Plot::MarkerStyle s, uint8_t uSize) 23 | { 24 | Style = s; 25 | Size = uSize; 26 | } 27 | 28 | Plot::MarkerStyle Style; 29 | uint8_t Size; 30 | }; 31 | 32 | class RGBColor 33 | { 34 | public: 35 | RGBColor(uint8_t uRed, uint8_t uGreen, uint8_t uBlue) 36 | { 37 | PackedValue = uRed; 38 | PackedValue = (PackedValue << 8) | uGreen; 39 | PackedValue = (PackedValue << 8) | uBlue; 40 | } 41 | 42 | RGBColor(uint32_t uPackedValue) 43 | { 44 | PackedValue = uPackedValue; 45 | } 46 | 47 | 48 | uint32_t PackedValue; 49 | }; 50 | -------------------------------------------------------------------------------- /src/UdpCommandHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include "UdpParser.h" 6 | #include "UdpManager.h" 7 | 8 | template class UdpCommandHandler 9 | : public MLP::CommandDispatcherBase, public MLP::UdpParser 10 | { 11 | // Array of commands we can match & dispatch. 12 | MLP::CommandCallback m_Commands[MAX_COMMANDS]; 13 | 14 | // Array of variables we can match & set/print 15 | MLP::VariableMap m_Variables[MAX_VARIABLES]; 16 | 17 | // Buffer for receiving packets into . 18 | char m_achBuffer[RECEIVE_BUFFER_SIZE]; 19 | 20 | public: 21 | 22 | UdpCommandHandler(UdpManager& rConnectionManager) 23 | : CommandDispatcherBase(m_Commands, MAX_COMMANDS, m_Variables, MAX_VARIABLES) 24 | , UdpParser(*(static_cast(this)), m_achBuffer, sizeof(m_achBuffer), rConnectionManager.GetConnection()) 25 | { 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/UdpResponseStream.cpp: -------------------------------------------------------------------------------- 1 | #include "UdpResponseStream.h" 2 | #include 3 | 4 | using namespace MLP; 5 | 6 | UdpResponseStream::UdpResponseStream(UDP &rConnection, IPAddress ipDestinationAddress, uint16_t uDestinationPort) 7 | : MLPMsgDestination(m_achBuffer, sizeof(m_achBuffer)) 8 | , m_rConnection(rConnection) 9 | 10 | { 11 | m_bStartedPacket = false; 12 | m_ipDestinationAddress = ipDestinationAddress; 13 | m_uDestinationPort = uDestinationPort; 14 | } 15 | 16 | void UdpResponseStream::flush() 17 | { 18 | if (length() > 0) 19 | { 20 | if (!m_bStartedPacket) 21 | { 22 | m_rConnection.beginPacket(m_ipDestinationAddress, m_uDestinationPort); 23 | m_bStartedPacket = true; 24 | } 25 | 26 | m_rConnection.write((uint8_t*)c_str(), length()); 27 | } 28 | } 29 | 30 | void UdpResponseStream::EndTransmission() 31 | { 32 | flush(); 33 | 34 | if (m_bStartedPacket) 35 | { 36 | m_rConnection.endPacket(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/ScheduledReport/ScheduledReport.ino: -------------------------------------------------------------------------------- 1 | 2 | /* ********************************************************************************* 3 | * Example program to trigger a scheduled report in MegunoLink. 4 | * 5 | * More Information 6 | * - https://www.megunolink.com/documentation/scheduled-reporting/ 7 | * - https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 8 | * ********************************************************************************* */ 9 | 10 | #include "MegunoLink.h" 11 | #include "ArduinoTimer.h" 12 | 13 | Report ReportGenerator; 14 | ::ArduinoTimer ReportTimer; 15 | 16 | TimePlot ADCValuePlot; 17 | ::ArduinoTimer PlotTimer; 18 | 19 | void setup() 20 | { 21 | Serial.begin(9600); 22 | } 23 | 24 | void loop() 25 | { 26 | if (PlotTimer.TimePassed_Milliseconds(500)) 27 | { 28 | ADCValuePlot.SendData("A0", analogRead(0)); 29 | } 30 | 31 | if (ReportTimer.TimePassed_Seconds(10)) 32 | { 33 | ReportGenerator.GenerateNow(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/Services/SpeechAndAudio/SpeechAndAudio.ino: -------------------------------------------------------------------------------- 1 | /* ************************************** 2 | * This example demonstrates text-to- 3 | * speech and audio playback in MegunoLink. 4 | * Open the companion MegunoLink project file 5 | * (SpeechAndAudio.mlpz) in the same folder 6 | * as this Arduino sketch. 7 | * 8 | * For more information see: 9 | * https://www.megunolink.com/documentation/play-sounds/ 10 | * https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 11 | */ 12 | #include "MegunoLink.h" 13 | #include "ArduinoTimer.h" 14 | 15 | int nCounter = 10; 16 | ::ArduinoTimer Countdown; 17 | Audio Sounds; 18 | 19 | void setup() 20 | { 21 | Serial.begin(9600); 22 | } 23 | 24 | void loop() 25 | { 26 | if (Countdown.TimePassed_Seconds(2)) 27 | { 28 | if (nCounter > 0) 29 | { 30 | Sounds.Speak(nCounter); 31 | } 32 | if (nCounter == 0) 33 | { 34 | Sounds.PlayAudioClip(F("Explosion")); 35 | } 36 | --nCounter; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/PrintBuffer.h: -------------------------------------------------------------------------------- 1 | /* *********************************************************************** 2 | * Buffers output to an object supporting the Print interface. 3 | * Writes are stored in a RAM buffer and sent when the internal buffer is 4 | * full, a new-line is encountered or when flush is called directly. 5 | * *********************************************************************** */ 6 | 7 | #include "MLPMsgBuffer.h" 8 | 9 | namespace MLP 10 | { 11 | template 12 | class PrintBuffer : public MLPMsgDestination 13 | { 14 | protected: 15 | char m_achBuffer[BufferSize]; 16 | 17 | Print& m_rDestination; 18 | 19 | public: 20 | PrintBuffer(Print& rDestination) 21 | : MLPMsgDestination(m_achBuffer, sizeof(m_achBuffer)) 22 | , m_rDestination(rDestination) 23 | { 24 | 25 | } 26 | 27 | virtual void flush() override 28 | { 29 | m_rDestination.write(c_str(), length()); 30 | begin(); 31 | } 32 | 33 | }; 34 | 35 | } // namespace MLP 36 | -------------------------------------------------------------------------------- /src/TCPCommandHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "CommandDispatcherBase.h" 5 | #include "utility/StreamParser.h" 6 | #include "TcpManager.h" 7 | 8 | template 9 | class TcpCommandHandler : public MLP::CommandDispatcherBase, public MLP::StreamParser 10 | { 11 | // Array of commands we can match & dispatch. 12 | MLP::CommandCallback m_Commands[MAX_COMMANDS]; 13 | 14 | // Array of variables we can match & set/print 15 | MLP::VariableMap m_Variables[MAX_VARIABLES]; 16 | 17 | // Buffer for receiving packets into . 18 | char m_achBuffer[RECEIVE_BUFFER_SIZE]; 19 | 20 | public: 21 | 22 | TcpCommandHandler(ITcpManager& rConnectionManager) 23 | : CommandDispatcherBase(m_Commands, MAX_COMMANDS, m_Variables, MAX_VARIABLES) 24 | , StreamParser(*(static_cast(this)), m_achBuffer, sizeof(m_achBuffer), rConnectionManager.GetConnection()) 25 | { 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/utility/CRC.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "CRC.h" 3 | 4 | #if defined(__AVR__) 5 | 6 | #include 7 | 8 | #else 9 | 10 | // Backup CRC algorithm where not supported by native library. For compatibility with AVR 11 | // checksum implementation: https://www.nongnu.org/avr-libc/user-manual/group__util__crc.html#ga95371c87f25b0a2497d9cba13190847f 12 | uint16_t _crc16_update(uint16_t crc, uint8_t data) 13 | { 14 | int i; 15 | crc ^= data; 16 | for (i = 0; i < 8; ++i) 17 | { 18 | if (crc & 1) 19 | crc = (crc >> 1) ^ 0xA001; 20 | else 21 | crc = (crc >> 1); 22 | } 23 | return crc; 24 | } 25 | 26 | #endif 27 | 28 | uint16_t CalculateChecksum(uint8_t const* pData, uint16_t uLength, uint16_t uSeed /*= 0xffff*/) 29 | { 30 | uint16_t uChecksum = uSeed; 31 | while (uLength--) 32 | { 33 | uChecksum = _crc16_update(uChecksum, *pData++); 34 | } 35 | return uChecksum; 36 | } 37 | 38 | uint16_t CalculateChecksum(uint8_t uData, uint16_t uSeed) 39 | { 40 | return _crc16_update(uSeed, uData); 41 | } 42 | -------------------------------------------------------------------------------- /src/CommandHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include "CommandProcessor.h" 6 | 7 | #include "CommandDispatcherBase.h" 8 | #include "utility/StreamParser.h" 9 | 10 | template class CommandHandler : public MLP::CommandDispatcherBase, public MLP::StreamParser 11 | { 12 | // Array of commands we can match & dispatch. 13 | MLP::CommandCallback m_Commands[MAX_COMMANDS]; 14 | 15 | // Array of variables we can match & set/print 16 | MLP::VariableMap m_Variables[MAX_VARIABLES]; 17 | 18 | // Buffer for data received. 19 | char m_achBuffer[CP_SERIAL_BUFFER_SIZE]; 20 | 21 | public: 22 | 23 | CommandHandler(Stream &rSourceStream = Serial, char chStartOfMessage = '!', char chEndOfMessage = '\r') 24 | : CommandDispatcherBase(m_Commands, MAX_COMMANDS, m_Variables, MAX_VARIABLES) 25 | , StreamParser(*(static_cast(this)), m_achBuffer, sizeof(m_achBuffer), rSourceStream, chStartOfMessage, chEndOfMessage) 26 | { 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /src/UdpParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CommandDispatcherBase.h" 4 | #include "Udp.h" 5 | #include "ArduinoTimer.h" 6 | #include "BlockParser.h" 7 | 8 | namespace MLP 9 | { 10 | class UdpParser : protected BlockParser 11 | { 12 | protected: 13 | 14 | // The commands to dispatch messages to. 15 | CommandDispatcherBase& m_rDispatcher; 16 | 17 | // Object responsible for sending and receiving UdpPackets. 18 | UDP& m_rConnection; 19 | 20 | // A buffer to collect commands. 21 | char * const m_pchBuffer; 22 | 23 | // Size of m_pchBuffer [bytes]. 24 | const size_t m_szMaxBufferSize; 25 | 26 | // Timer to perioidcally check for network packets. 27 | ::ArduinoTimer m_tmrPacketCheck; 28 | 29 | // Interval between checking for new packets. 30 | const unsigned PacketCheckInterval = 10; // ms 31 | 32 | public: 33 | UdpParser(MLP::CommandDispatcherBase& rDispatcher, char* pchReceiveBuffer, size_t szReceiveBuffer, UDP& rConnection); 34 | 35 | void Process(); 36 | 37 | private: 38 | }; 39 | } // namespace MLP 40 | -------------------------------------------------------------------------------- /src/MegunoLinkNetwork.cpp: -------------------------------------------------------------------------------- 1 | #include "MegunoLinkNetwork.h" 2 | 3 | MegunoLinkNetwork::MegunoLinkNetwork(INetworkDestination& rDestination) 4 | : MLPMsgDestination(m_achTransmitBuffer, BufferSize) 5 | , MegunoLinkBufferWrapper(this) 6 | , m_pAddressedDestination(&rDestination) 7 | , m_pStreamDestination(nullptr) 8 | { 9 | m_uDestinationPort = 0; 10 | } 11 | 12 | MegunoLinkNetwork::MegunoLinkNetwork(IStreamDestination& rDestination) 13 | : MLPMsgDestination(m_achTransmitBuffer, BufferSize) 14 | , MegunoLinkBufferWrapper(this) 15 | , m_pAddressedDestination(nullptr) 16 | , m_pStreamDestination(&rDestination) 17 | { 18 | m_uDestinationPort = 0; 19 | } 20 | 21 | void MegunoLinkNetwork::SetDestination(IPAddress DestinationAddress, uint16_t uDestinationPort) 22 | { 23 | m_ipDestination = DestinationAddress; 24 | m_uDestinationPort = uDestinationPort; 25 | } 26 | 27 | void MegunoLinkNetwork::flush() 28 | { 29 | if (m_pAddressedDestination != nullptr) 30 | { 31 | m_pAddressedDestination->SendBlock(c_str(), length(), m_ipDestination, m_uDestinationPort); 32 | } 33 | if (m_pStreamDestination != nullptr) 34 | { 35 | m_pStreamDestination->SendBlock(c_str(), length()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/utility/TCPConnection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) 4 | 5 | #include 6 | #include 7 | 8 | #if defined(ARDUINO_ARCH_ESP32) 9 | #include 10 | #elif defined(ARDUINO_ARCH_ESP8266) 11 | #include 12 | #endif 13 | 14 | 15 | #include "StreamParser.h" 16 | 17 | namespace MLP 18 | { 19 | template 20 | class TCPConnection 21 | : public MLP::StreamParser 22 | { 23 | // Buffer for data received. 24 | char m_achBuffer[CP_SERIAL_BUFFER_SIZE]; 25 | 26 | public: 27 | TCPConnection() 28 | : MLP::StreamParser(m_achBuffer, CP_SERIAL_BUFFER_SIZE) 29 | { 30 | } 31 | 32 | void Init(MLP::CommandDispatcherBase &rCommandHandler, char chStartOfMessage = '!', char chEndOfMessage = '\r') 33 | { 34 | Reset(); 35 | m_pCommandHandler = &rCommandHandler; 36 | m_chStartOfMessage = chStartOfMessage; 37 | m_chEndOfMessage = chEndOfMessage; 38 | m_pSource = NULL; 39 | } 40 | 41 | 42 | void SetStream(Stream *pStream) 43 | { 44 | m_pSource = pStream; 45 | Reset(); 46 | } 47 | 48 | WiFiClient m_Client; 49 | }; 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /examples/TimePlot/PlotAnalogValue/PlotAnalogValue.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program to plot data from the analoge to digital converter on a chart. 3 | * Visit http://www.megunolink.com/documentation/plotting/ 4 | * for more information. 5 | * ********************************************************************************************** */ 6 | 7 | #include "MegunoLink.h" // Helpful functions for communicating with MegunoLink Pro. 8 | 9 | // Millis value when the data was last sent. 10 | long LastSent; 11 | 12 | // Interval (milliseconds) between sending analog data 13 | const unsigned SendInterval = 200; // [ms] 14 | 15 | // The plot we are sending data to. A TimePlot is used here 16 | TimePlot MyPlot; 17 | 18 | void setup() 19 | { 20 | Serial.begin(9600); 21 | 22 | LastSent = millis(); 23 | 24 | MyPlot.SetTitle("My Analog Measurement"); 25 | MyPlot.SetXLabel("Time"); 26 | MyPlot.SetYLabel("Value"); 27 | MyPlot.SetSeriesProperties("ADCValue", Plot::Magenta, Plot::Solid, 2, Plot::Square); 28 | } 29 | 30 | void loop() 31 | { 32 | if ((millis() - LastSent) > SendInterval) 33 | { 34 | LastSent = millis(); 35 | 36 | int DataValue = analogRead(0); 37 | MyPlot.SendData("ADCValue", DataValue); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/UdpManager.h: -------------------------------------------------------------------------------- 1 | /* *********************************************************************** 2 | * UdpManager 3 | * Maintains Udp connection 4 | * *********************************************************************** */ 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include "NetworkDestination.h" 11 | 12 | class UdpManager : public INetworkDestination 13 | { 14 | private: 15 | const uint16_t m_uListenPort; 16 | 17 | UDP &m_rConnection; 18 | 19 | IPAddress m_DefaultDestinationAddress; 20 | uint16_t m_uDefaultDestinationPort; 21 | 22 | protected: 23 | UdpManager(UDP &rConnection, uint16_t uListenPort, uint16_t uDestinationPort = 0); 24 | 25 | public: 26 | bool OnNetworkConnected(); 27 | void OnNetworkConnectionLost(); 28 | 29 | // Placeholder to maintain a consistent interface. 30 | void Process() {} 31 | 32 | void SetDefaultDestinationPort(uint16_t uDestinationPort); 33 | void SetDefaultDestination(IPAddress DestinationAddress, uint16_t uDestinationPort = 0); 34 | void SetDefaultDestinationToBroadcast(); 35 | 36 | bool SendBlock(const char* pchData, size_t szLength); 37 | virtual bool SendBlock(const char* pchData, size_t szLength, IPAddress DestinationAddress, uint16_t uDestinationPort = 0) override; 38 | 39 | UDP& GetConnection() { return m_rConnection; } 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /examples/MessageLogger/SendCSVData/SendCSVData.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program to send CSV data through Megunolinks message system. These are separated from the 3 | * main serial stream and can either be displayed (Message Monitor) or logged (Message Logger). 4 | * Visit http://www.megunolink.com/documentation/monitoring-data/ to see how to use our message monitor and 5 | * http://www.megunolink.com/documentation/logging-data/ to use our message logger. 6 | * ********************************************************************************************** */ 7 | #include "MegunoLink.h" 8 | 9 | Message MyCSVMessage("Data"); //"Data" = the taget message channel (remember to select this in megunolink) 10 | 11 | // When logging make sure you specifiy a path for the logfile and enable logging. 12 | 13 | void setup() 14 | { 15 | Serial.begin(9600); 16 | } 17 | 18 | 19 | 20 | void loop() 21 | { 22 | 23 | // Sends the microcontroller time, and the analog value using a comma separated format 24 | // perfect for use with tools like excel and matlab 25 | MyCSVMessage.Begin(); 26 | Serial.print(millis()); 27 | Serial.print(","); 28 | Serial.print(analogRead(A0)); 29 | Serial.print(","); 30 | MyCSVMessage.End(); 31 | 32 | delay(100); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /examples/InterfacePanel/SetParametersWithEEPROM/SetParametersWithEEPROM.ino: -------------------------------------------------------------------------------- 1 | #include "MegunoLink.h" 2 | #include "CommandHandler.h" 3 | #include "EEPROMStore.h" 4 | 5 | 6 | //EEPROM Storage 7 | struct TurtleSettings 8 | { 9 | int NumberOfTurtles; 10 | 11 | void Reset() 12 | { 13 | NumberOfTurtles = 0; // Amount of time the LED remains on [milliseconds] 14 | } 15 | }; 16 | EEPROMStore TurtleConfig; 17 | 18 | 19 | 20 | //Command Handler 21 | CommandHandler<> SerialCommandHandler; 22 | void Cmd_GetTurtleCount(CommandParameter &Parameters) 23 | { 24 | Parameters.GetSource().print(F("Number of turtles = ")); 25 | Parameters.GetSource().println(TurtleConfig.Data.NumberOfTurtles); 26 | } 27 | 28 | void Cmd_SetTurtleCount(CommandParameter &Parameters) 29 | { 30 | TurtleConfig.Data.NumberOfTurtles=Parameters.NextParameterAsInteger(); 31 | TurtleConfig.Save(); //Save to EEPROM 32 | } 33 | 34 | void setup() 35 | { 36 | Serial.begin(9600); 37 | Serial.println("MegunoLink Pro Turtle Monitor"); 38 | Serial.println("-----------------------------"); 39 | 40 | TurtleConfig.Load(); //Restore from EEPROM 41 | 42 | SerialCommandHandler.AddCommand(F("SetTurtleCount"), Cmd_SetTurtleCount); 43 | SerialCommandHandler.AddCommand(F("GetTurtleCount"), Cmd_GetTurtleCount); 44 | 45 | } 46 | 47 | void loop() 48 | { 49 | SerialCommandHandler.Process(); 50 | } 51 | -------------------------------------------------------------------------------- /examples/XYPlot/PlotAnalogValue/PlotAnalogValue.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program to plot data from the analoge to digital converter on an X-Y Plot 3 | * Visit http://www.megunolink.com/documentation/plotting/ 4 | * for more information. 5 | * ********************************************************************************************** */ 6 | 7 | #include "MegunoLink.h" // Helpful functions for communicating with MegunoLink Pro. 8 | 9 | // Millis value when the data was last sent. 10 | long LastSent; 11 | 12 | // Interval (milliseconds) between sending analog data 13 | const unsigned SendInterval = 200; // [ms] 14 | 15 | // The plot we are sending data to. A TimePlot is used here 16 | XYPlot MyPlot; 17 | 18 | void setup() 19 | { 20 | Serial.begin(9600); 21 | 22 | LastSent = millis(); 23 | 24 | MyPlot.SetTitle("My Analog Measurement"); 25 | MyPlot.SetXLabel("Arduino Timer [mS]"); 26 | MyPlot.SetYLabel("Value"); 27 | MyPlot.SetSeriesProperties("ADCValue", Plot::Magenta, Plot::Solid, 2, Plot::Square); 28 | } 29 | 30 | void loop() 31 | { 32 | if ((millis() - LastSent) > SendInterval) 33 | { 34 | LastSent = millis(); 35 | 36 | int DataValue = analogRead(0); 37 | MyPlot.SendData("ADCValue", millis(),DataValue); //millis() goes on the xaxis, DataValue goes on the yaxis 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/utility/CommandParameter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class CommandParameter 6 | { 7 | // Buffer of parameters. As we work through each one, it gets null terminated. 8 | char *m_pchBuffer; 9 | 10 | // Offset to next parameter in buffer. 11 | uint8_t m_uNextParameter; 12 | 13 | // Sender address, if this command was sent from an IP address 14 | // and we know the remote address. Null otherwise. 15 | IPAddress* m_pSender; 16 | 17 | public: 18 | CommandParameter(Print &rSourceStream, char *pchBuffer, uint8_t nFirstParameter, IPAddress* pSender = nullptr); 19 | 20 | // The stream that the parameter came from (for replies, for example) 21 | Print& Response; 22 | Print& GetSource() { return Response; } 23 | 24 | const char *NextParameter(); 25 | const char *RemainingParameters(); 26 | 27 | int NextParameterAsInteger(int nDefault = -1); 28 | long NextParameterAsLong(long nDefault = -1); 29 | unsigned long NextParameterAsUnsignedLong(unsigned long nDefault = -1); 30 | double NextParameterAsDouble(double fDefault = 0.0); 31 | 32 | uint8_t NextParameterAsU8FromHex(uint8_t uDefault = 0); 33 | uint16_t NextParameterAsU16FromHex(uint16_t uDefault = 0); 34 | uint32_t NextParameterAsU32FromHex(uint32_t uDefault = 0); 35 | 36 | bool GetSenderAddress(IPAddress& rAddress); 37 | 38 | private: 39 | uint8_t HexValueOf(char ch); 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /.github/workflows/githubci.yml: -------------------------------------------------------------------------------- 1 | name: Arduino Library CI 2 | 3 | on: [pull_request, push, repository_dispatch] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/setup-python@v4 11 | with: 12 | python-version: '3.x' 13 | - uses: actions/checkout@v3 14 | - uses: actions/checkout@v3 15 | with: 16 | repository: PaulMartinsen/ci-arduino 17 | path: ci 18 | 19 | - name: Install the prerequisites 20 | run: bash ci/actions_install.sh 21 | 22 | # - name: Check for correct code formatting with clang-format 23 | # run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r . 24 | 25 | # - name: Check for correct documentation with doxygen 26 | # env: 27 | # GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} 28 | # PRETTYNAME : "MegunoLink library for Arduino" 29 | # run: bash ci/doxy_gen_and_deploy.sh 30 | 31 | - name: Set configuration 32 | run: arduino-cli config set library.enable_unsafe_install true 33 | 34 | - name: Install test dependencies 35 | run: arduino-cli lib install --git-url https://github.com/arduino-libraries/Servo --git-url https://github.com/Megunolink/WiFiConfig --git-url https://github.com/njh/EtherCard --git-url https://github.com/arduino-libraries/Ethernet 36 | 37 | - name: Test the code on supported platforms 38 | run: python3 ci/build_platform.py main_platforms 39 | -------------------------------------------------------------------------------- /src/UdpParser.cpp: -------------------------------------------------------------------------------- 1 | #include "UdpParser.h" 2 | #include "PrintBuffer.h" 3 | #include "UdpResponseStream.h" 4 | 5 | using namespace MLP; 6 | 7 | UdpParser::UdpParser(MLP::CommandDispatcherBase &rDispatcher, char *pchReceiveBuffer, size_t szReceiveBuffer, UDP& rConnection) 8 | : m_rDispatcher(rDispatcher), m_rConnection(rConnection), m_pchBuffer(pchReceiveBuffer), m_szMaxBufferSize(szReceiveBuffer) 9 | { 10 | } 11 | 12 | void UdpParser::Process() 13 | { 14 | if (m_tmrPacketCheck.TimePassed_Milliseconds(PacketCheckInterval)) 15 | { 16 | int nAvailable = m_rConnection.parsePacket(); 17 | if (nAvailable > 0) 18 | { 19 | if (nAvailable <= (int)m_szMaxBufferSize) 20 | { 21 | char *pchCommand = m_pchBuffer; 22 | int nCommandLength = m_rConnection.read(pchCommand, m_szMaxBufferSize - 1); 23 | if (nCommandLength > 0 && FindCommand(pchCommand, nCommandLength)) 24 | { 25 | IPAddress ipSource = m_rConnection.remoteIP(); 26 | UdpResponseStream Response(m_rConnection, ipSource, m_rConnection.remotePort()); 27 | m_rDispatcher.DispatchCommand(pchCommand, Response, &ipSource); 28 | Response.EndTransmission(); 29 | } 30 | } 31 | else 32 | { 33 | Serial.println(F("Err: Udp Ovflw")); 34 | // read and discard; buffer is too small to process. 35 | while (nAvailable-- > 0) 36 | { 37 | m_rConnection.read(); 38 | } 39 | } 40 | } 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | MegunoLink library for Arduino Change History 2 | ============================================= 3 | 4 | 1.42 5 | ---- 6 | * Fixed compatibility issues with Arduino mbed platforms (e.g., Pi Pico). Thanks to [maxgerhardt](https://github.com/maxgerhardt) for identifying this problem. 7 | * Miscellaneous bug fixes and tidy up. 8 | * Added continuous integration work flow to build all examples on several platforms following suggestion from [maxgerhardt](https://github.com/maxgerhardt). 9 | 10 | 1.41 11 | ---- 12 | * Updated examples to use ESP command handler for Tcp connections 13 | * Excluded `MDNS.update();` call for ESP32, where it is not supported 14 | * Fixed compile time error when sending SpecialParameters::CurrentTime to record table 15 | * Fixed examples to use correct name for TcpCommandHandler on ESP hardware. 16 | 17 | 1.40 18 | ---- 19 | * Added `RGBColor` class to send custom colors to plots and resolve build errors for some micros. 20 | * Added support for device file transfer visualizer. 21 | * New examples for speech and audio. 22 | * Added support to expand command handler with pluggable modules. 23 | * Added support to send double precision values to XYPlots without casting. 24 | * Added core support for Udp and Tcp communications. 25 | * Cleaned up and consolodated plotting and table methods. 26 | * Fixed build errors for Teensy. 27 | * Fixed build errors for Due. 28 | * Added library meta data file for PlatformIO/Visual Studio Code. 29 | * Improvements to const-correctness. 30 | -------------------------------------------------------------------------------- /examples/RecordTable/SendToCell/SendToCell.ino: -------------------------------------------------------------------------------- 1 | /* ************************************************************************ 2 | Send to Record Table cells. 3 | 4 | This example demonstrates sending data to individual cells in a MegunoLink 5 | record table. Every second it sends a random symbol to a random cell in 6 | the record table. 7 | 8 | The MegunoLink project for this example is in the same folder as this 9 | Arduino code. To download a free MegunoLink trial, visit: 10 | - http://www.MegunoLink.com to download MegunoLink. 11 | 12 | More Information 13 | - https://www.megunolink.com/documentation/table/record-table/ 14 | - https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 15 | 16 | ************************************************************************ */ 17 | 18 | #include "MegunoLink.h" 19 | #include "ArduinoTimer.h" 20 | 21 | RecordTable MyTable; 22 | ::ArduinoTimer SendDataTimer; 23 | 24 | void setup() 25 | { 26 | Serial.begin(115200); 27 | delay(1000); 28 | 29 | Serial.print("MegunoLink Record Table Cell Example\n\n\n"); 30 | } 31 | 32 | void loop() 33 | { 34 | if (SendDataTimer.TimePassed_Milliseconds(1000)) 35 | { 36 | const int MaxRows = 10; 37 | const int MaxColumns = 10; 38 | 39 | char Symbols[] = {'x', 'o', '+', '*'}; 40 | 41 | int Row = random(MaxRows); 42 | int Column = random(MaxColumns); 43 | int SymbolIndex = random(sizeof(Symbols)); 44 | 45 | MyTable.SetValue(Row, Column, Symbols[SymbolIndex]); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ArduinoTimer.cpp: -------------------------------------------------------------------------------- 1 | #include "ArduinoTimer.h" 2 | 3 | ::ArduinoTimer::ArduinoTimer() 4 | { 5 | m_uStartTime = 0; 6 | } 7 | 8 | bool ::ArduinoTimer::TimePassed_Milliseconds(uint32_t uPeriod, bool bAutoReset) 9 | { 10 | uint32_t uNow; 11 | 12 | uNow = millis(); 13 | if (uNow - m_uStartTime >= uPeriod) 14 | { 15 | if (bAutoReset) 16 | m_uStartTime = uNow; 17 | return true; 18 | } 19 | 20 | return false; 21 | } 22 | 23 | bool ::ArduinoTimer::TimePassed_Seconds(uint16_t uPeriod, bool bAutoReset) 24 | { 25 | uint32_t uNow; 26 | 27 | uNow = millis(); 28 | if ((uNow - m_uStartTime)/1000 >= uPeriod) 29 | { 30 | if (bAutoReset) 31 | m_uStartTime = uNow; 32 | return true; 33 | } 34 | 35 | return false; 36 | } 37 | 38 | bool ::ArduinoTimer::TimePassed_Minutes(uint16_t uPeriod, bool bAutoReset) 39 | { 40 | uint32_t uNow; 41 | uint32_t uDelta; 42 | 43 | uNow = millis(); 44 | uDelta = uNow - m_uStartTime; 45 | uDelta /= 60000; // => s 46 | if (uDelta >= uPeriod) 47 | { 48 | if (bAutoReset) 49 | m_uStartTime = uNow; 50 | return true; 51 | } 52 | 53 | return false; 54 | } 55 | 56 | bool ::ArduinoTimer::TimePassed_Hours( uint16_t uPeriod, bool bAutoReset /*= true*/ ) 57 | { 58 | uint32_t uNow; 59 | uint32_t uDelta; 60 | 61 | uNow = millis(); 62 | uDelta = uNow - m_uStartTime; 63 | uDelta /= 60000; // => s 64 | uDelta /= 60; // => h 65 | if (uDelta >= uPeriod) 66 | { 67 | if (bAutoReset) 68 | m_uStartTime = uNow; 69 | return true; 70 | } 71 | 72 | return false; 73 | } 74 | -------------------------------------------------------------------------------- /examples/InterfacePanel/ServoControl/ServoControl.ino: -------------------------------------------------------------------------------- 1 | /* ************************************************************************ 2 | Servo Control 3 | This program demonstrates how MegunoLink's Interface Panel and our command 4 | handler Arduino library can be used to control a servo. 5 | 6 | The example folder also contains a MegunoLink project, with an Interface 7 | Panel to control the parameters. 8 | Visit: 9 | * http://www.MegunoLink.com to download MegunoLink. 10 | ************************************************************************ */ 11 | 12 | #include 13 | #include "CommandHandler.h" 14 | 15 | #define ServoPin 9 16 | 17 | Servo MyServo; // create servo object to control a servo 18 | CommandHandler<> SerialCommandHandler; // create command handler object 19 | 20 | void Cmd_SetServoPosition(CommandParameter &Parameters) 21 | { 22 | int ReceivedPosition = Parameters.NextParameterAsInteger(); // grab sent number as integer 23 | 24 | Serial.print("Position Received: "); 25 | Serial.println(ReceivedPosition); 26 | 27 | MyServo.write(ReceivedPosition); // sets the servo position according to received value 28 | } 29 | 30 | void setup() 31 | { 32 | Serial.begin(9600); 33 | delay(1000); 34 | Serial.print("Setup started.."); 35 | 36 | MyServo.attach(ServoPin); // attaches the servo on pin 9 to the servo object 37 | SerialCommandHandler.AddCommand(F("SetServoPos"), Cmd_SetServoPosition); // Attach command 38 | 39 | Serial.println("done."); 40 | } 41 | 42 | void loop() 43 | { 44 | SerialCommandHandler.Process(); // Process serial commands 45 | } 46 | -------------------------------------------------------------------------------- /src/MLPMsgBuffer.h: -------------------------------------------------------------------------------- 1 | /* *********************************************************************** 2 | * MLPMsgDestination 3 | * Implements a buffer for MegunoLink messages for block transports such 4 | * as Mqtt and Tcp. The message is assembled in a, fixed-size, internal 5 | * buffer and sent on new-line (or when the buffer is full). 6 | * *********************************************************************** */ 7 | 8 | #pragma once 9 | #include "Print.h" 10 | 11 | class MLPMsgDestination : public Print 12 | { 13 | protected: 14 | 15 | /// 16 | /// Buffer that we are writing to. Buffer should 17 | /// be large enough to hold the biggest message we'll send. 18 | /// 19 | char * const m_pchStart; 20 | 21 | /// 22 | /// Size of the buffer. 23 | /// 24 | int const m_nBufferSize; 25 | 26 | /// 27 | /// Next location in buffer to write to 28 | /// 29 | char* m_pchNext; 30 | 31 | public: 32 | 33 | MLPMsgDestination(char* pchStart, int nLength); 34 | 35 | void begin(); 36 | 37 | inline size_t length() const 38 | { 39 | return m_pchNext - m_pchStart; 40 | } 41 | 42 | inline size_t available() const 43 | { 44 | return capacity() - length(); 45 | } 46 | 47 | inline size_t capacity() const 48 | { 49 | return m_nBufferSize; 50 | } 51 | 52 | inline char const* c_str() const 53 | { 54 | return m_pchStart; 55 | } 56 | 57 | virtual size_t write(uint8_t uValue) override; 58 | 59 | virtual void flush() = 0; 60 | 61 | virtual void EndTransmission(); 62 | }; 63 | -------------------------------------------------------------------------------- /examples/InterfacePanel/BlinkPictureBox/BlinkPictureBox.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | This example demonstrates the ability to show and hide pictures in MegunoLink's Interface Panel. 4 | The control of this showing/hiding comes from the Arduino end providing a way to do basic animation. 5 | 6 | More Information 7 | * https://www.megunolink.com/documentation/build-arduino-interface/ 8 | * https://www.megunolink.com/documentation/interface-panel/ 9 | 10 | This Example Requires: 11 | * The MegunoLink arduino library https://www.megunolink.com/documentation/arduino-integration/ 12 | 13 | MegunoLink Interface 14 | You can download a pre-made interface from here: 15 | https://github.com/Megunolink/MLP/raw/master/examples/InterfacePanel/BlinkPictureBox/BlinkPictureBox.mlpz 16 | 17 | You can find out more about MegunoLink and download a free trial from here 18 | https://www.megunolink.com/ 19 | https://www.megunolink.com/download/ 20 | ************************************************************************************************/ 21 | 22 | 23 | #include "MegunoLink.h" 24 | 25 | InterfacePanel Panel; 26 | 27 | void setup() { 28 | // put your setup code here, to run once: 29 | Serial.begin(9600); 30 | } 31 | 32 | void loop() { 33 | // put your main code here, to run repeatedly: 34 | Panel.ShowControl("pbRed"); 35 | delay(400); 36 | Panel.HideControl("pbRed"); 37 | delay(450); 38 | Panel.ShowControl("pbGreen"); 39 | delay(400); 40 | Panel.HideControl("pbGreen"); 41 | delay(450); 42 | } 43 | -------------------------------------------------------------------------------- /examples/RecordTable/BasicRecordTable/BasicRecordTable.ino: -------------------------------------------------------------------------------- 1 | /* ************************************************************************ 2 | Basic Demonstration of MegunoLinks Record Table 3 | This example demonstrates MegunoLinks Record Table visualiser by outputting 4 | 10 lines of data every 5 seconds. The table is then reset and 10 new records 5 | are generated. 6 | 7 | The MegunoLink project for this example is in the same folder as this 8 | Arduino code. To download a free MegunoLink trial, visit: 9 | - http://www.MegunoLink.com to download MegunoLink. 10 | 11 | More Information 12 | - https://www.megunolink.com/documentation/table/record-table/ 13 | - https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 14 | ************************************************************************ */ 15 | 16 | #include "MegunoLink.h" 17 | #include "ArduinoTimer.h" 18 | 19 | RecordTable MyTable; 20 | ::ArduinoTimer TableRefreshTimer; 21 | 22 | void setup() 23 | { 24 | Serial.begin(115200); 25 | delay(1000); 26 | 27 | Serial.print("MegunoLink Record Table Basic Example\n\n\n"); 28 | 29 | MyTable.SetNumberOfDecimalPlaces(5); 30 | } 31 | 32 | void loop() 33 | { 34 | 35 | if (TableRefreshTimer.TimePassed_Milliseconds(5000)) 36 | { 37 | float AValue = 1e-5; 38 | MyTable.ClearAllRows(); 39 | for (int i = 0; i < 10; i++) 40 | { 41 | bool IsOdd = (i%2) != 0; 42 | MyTable.AddRow(i, IsOdd, millis(), SpecialParameters::CurrentTime, rand(), "fish", analogRead(0), AValue); 43 | AValue = AValue * 2; 44 | delay(100); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/ArduinoTimer.h: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * A wraper to simplify timed actions on the Arduino platform. 3 | * Usage: 4 | * // Create a class or global timer variable. 5 | * ArduinoTimer MyTimer; 6 | * 7 | * // For timed action. 8 | * if (MyTimer.TimePassed_Seconds(10)) 9 | * { 10 | * Serial.println("Another 10 seconds has ellapsed"); 11 | * } 12 | * ***************************************************************************** */ 13 | 14 | #pragma once 15 | #include 16 | 17 | class ArduinoTimer 18 | { 19 | uint32_t m_uStartTime; 20 | public: 21 | ArduinoTimer(); 22 | 23 | inline ArduinoTimer(bool bReset) __attribute__((always_inline)) 24 | { 25 | if (bReset) 26 | Reset(); 27 | } 28 | 29 | inline void Reset() __attribute__((always_inline)) 30 | { 31 | m_uStartTime = millis(); 32 | } 33 | 34 | inline uint32_t EllapsedMilliseconds() const __attribute__((always_inline)) 35 | { 36 | return millis() - m_uStartTime; 37 | } 38 | 39 | inline uint16_t EllapsedSeconds() const __attribute__((always_inline)) 40 | { 41 | return (millis() - m_uStartTime) / 1000; 42 | } 43 | 44 | bool TimePassed_Milliseconds(uint32_t uPeriod, bool bAutoReset = true); 45 | bool TimePassed_Seconds(uint16_t uPeriod, bool bAutoReset = true); 46 | bool TimePassed_Minutes(uint16_t uPeriod, bool bAutoReset = true); 47 | bool TimePassed_Hours(uint16_t uPeriod, bool bAutoReset = true); 48 | 49 | inline uint32_t StartTime() const __attribute__((always_inline)) 50 | { 51 | return m_uStartTime; 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /examples/MessageMonitor/SendCSVData/SendCSVData.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program to send CSV data through Megunolinks message system. These are separated from the 3 | * main serial stream and can either be displayed (Message Monitor) or logged (Message Logger). 4 | * Visit http://www.megunolink.com/documentation/monitoring-data/ to see how to use our message monitor and 5 | * http://www.megunolink.com/documentation/logging-data/ to use our message logger. 6 | * ********************************************************************************************** */ 7 | #include "MegunoLink.h" 8 | 9 | Message MyCSVMessage("Data"); //"Data" = the taget message channel (remember to select this in megunolink) 10 | 11 | // When logging make sure you specifiy a path for the logfile and enable logging. 12 | 13 | void setup() 14 | { 15 | Serial.begin(9600); 16 | } 17 | 18 | void loop() 19 | { 20 | // The values that we want to send... 21 | int Value1 = analogRead(A0); 22 | #if defined(A1) 23 | int Value2 = analogRead(A1); 24 | #else 25 | // Some boards only have 1 analog input. For them we'll get another value from the first port. 26 | int Value2 = analogRead(A0); 27 | #endif 28 | 29 | // Sends the microcontroller time, and the analog value using a comma separated format 30 | // perfect for use with tools like excel and matlab 31 | MyCSVMessage.Begin(); 32 | Serial.print(millis()); 33 | Serial.print(","); 34 | Serial.print(Value1); 35 | Serial.print(","); 36 | Serial.print(Value2); 37 | MyCSVMessage.End(); 38 | 39 | delay(100); 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/utility/StreamParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "CommandDispatcherBase.h" 4 | 5 | namespace MLP 6 | { 7 | class StreamParser 8 | { 9 | protected: 10 | MLP::CommandDispatcherBase *m_pCommandHandler; 11 | 12 | // The stream that we are parsing for commands. 13 | // Protected so that network command handlers (such as TCPCommandHandler) 14 | // can update with connection. If null, commands are not parsed. 15 | // Be sure to reset the parser whenever the source is changed. 16 | Stream *m_pSource; 17 | 18 | // Characters that signal start and end of message. 19 | // The buffer is reset when a start character is received. Commands 20 | // are dispatched when the end character is received. 21 | char m_chStartOfMessage, m_chEndOfMessage; 22 | 23 | private: 24 | // A buffer to collect commands. Buffer, and size, is provided. 25 | char * const m_pchBuffer; 26 | const unsigned m_uMaxBufferSize; 27 | 28 | // Index where next character will be placed in the buffer. 29 | unsigned m_uNextCharacter; 30 | 31 | // True iff an overflow has occured. Commands will not 32 | // be dispatched from buffers that overflow. 33 | bool m_bOverflow; 34 | 35 | protected: 36 | StreamParser(MLP::CommandDispatcherBase &rCommandHandler, char *pchReceiveBuffer, unsigned uBufferSize, 37 | Stream &rSourceStream = Serial, char chStartOfMessage = '!', char chEndOfMessage = '\r'); 38 | StreamParser(char *pchReceiveBuffer, unsigned uBufferSize); 39 | 40 | void DispatchMessage(); 41 | 42 | public: 43 | void Process(); 44 | void Reset(); 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /examples/ExponentialFilter/ExponentialFilter.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | In this example we demonstrate our Filter library. We sample data from an analog port then filter 4 | the data and plot both value to MegunoLink's Time Plot visualier. 5 | 6 | More Information 7 | * http://www.MegunoLink.com/documentation/arduino-libraries/exponential-filter/ 8 | * http://www.megunolink.com/documentation/plotting/ 9 | 10 | This Example Requires: 11 | * The MegunoLink arduino library https://www.megunolink.com/documentation/arduino-integration/ 12 | 13 | MegunoLink Interface 14 | You can download a pre-made interface from here: 15 | https://github.com/Megunolink/MLP/raw/master/examples/ExponentialFilter/ExponentialFilter.mlpz 16 | 17 | You can find out more about MegunoLink and download a free trial from here 18 | https://www.megunolink.com/ 19 | https://www.megunolink.com/download/ 20 | ************************************************************************************************/ 21 | 22 | #include "MegunoLink.h" 23 | #include "Filter.h" 24 | 25 | // Create a new exponential filter with a weight of 10 and initial value of 0. 26 | ExponentialFilter ADCFilter(10, 0); 27 | 28 | void setup() 29 | { 30 | Serial.begin(9600); 31 | Serial.println("Exponential Filter demo"); 32 | Serial.println("-----------------------"); 33 | } 34 | 35 | void loop() 36 | { 37 | int RawValue = analogRead(0); 38 | ADCFilter.Filter(RawValue); 39 | 40 | TimePlot Plot; 41 | Plot.SendData("Raw", RawValue); 42 | Plot.SendData("Filtered", ADCFilter.Current()); 43 | 44 | delay(100); 45 | } 46 | -------------------------------------------------------------------------------- /examples/InterfacePanel/ColorTest/ColorTest.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | This example demonstrates Megunolink's Interface Panel and its ability to be updated from commands 4 | sent from the Arduino. In this example we dynamically adjust the colour of a button on a pre-made 5 | interface. 6 | 7 | More Information 8 | * https://www.megunolink.com/documentation/interface-panel/ 9 | 10 | This Example Requires: 11 | * The MegunoLink arduino library https://www.megunolink.com/documentation/arduino-integration/ 12 | 13 | MegunoLink Interface 14 | You can download a pre-made interface from here: 15 | https://github.com/Megunolink/MLP/raw/master/examples/InterfacePanel/ColorTest/ColorTest.mlpz 16 | 17 | You can find out more about MegunoLink and download a free trial from here 18 | https://www.megunolink.com/ 19 | https://www.megunolink.com/download/ 20 | ************************************************************************************************/ 21 | 22 | #include "MegunoLink.h" 23 | 24 | void setup() 25 | { 26 | Serial.begin(9600); 27 | Serial.println("Color Test"); 28 | } 29 | 30 | void loop() 31 | { 32 | InterfacePanel UI; 33 | 34 | // Colours can be by name or hex string. 35 | // Named colours are here: https://msdn.microsoft.com/en-us/library/system.drawing.color(v=vs.110).aspx 36 | // Hex values are RRGGBB 37 | UI.SetBackColor("bttA", "Red"); 38 | UI.SetBackColor("bttB", "00FF00"); // Green 39 | 40 | delay(1000); 41 | 42 | UI.SetBackColor("bttA", "AliceBlue"); 43 | UI.SetBackColor("bttB", "FFFF00"); // Yellow 44 | 45 | delay(1000); 46 | } 47 | -------------------------------------------------------------------------------- /examples/InterfacePanel/ValueList/ValueList.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program to select list box values on a MegunoLink Pro User Interface Panel. 3 | * 4 | * This program periodically sends out commands to select items in two ValueList controls. Values 5 | * in the first control (named lbUser) are selected by index. Values in the second ValueList 6 | * control are selected by value. 7 | * ********************************************************************************************** */ 8 | 9 | #include "MegunoLink.h" // Helpful functions for communicating with MegunoLink Pro. 10 | 11 | // Millis value when the data was last sent. 12 | long LastSent; 13 | 14 | // Currently selected 'user' index value 15 | int UserIndex; 16 | 17 | // User ages we select 18 | int UserAge[] = { 3, 5, 22 }; 19 | const int UserAgeCount = sizeof(UserAge)/sizeof(UserAge[0]); 20 | 21 | // The user age we are going to select next 22 | int UserAgeIndex; 23 | 24 | // The interface panel we are sending data to 25 | InterfacePanel Panel("Test"); 26 | 27 | void setup() 28 | { 29 | Serial.begin(9600); 30 | 31 | LastSent = millis(); 32 | UserIndex = 0; 33 | UserAgeIndex = 0; 34 | } 35 | 36 | void loop() 37 | { 38 | if ((millis() - LastSent) > 1500) 39 | { 40 | LastSent = millis(); 41 | 42 | // Select the next item by index. 43 | Panel.SetListIndex("lbUser", UserIndex); 44 | UserIndex = (UserIndex + 1) % 3; 45 | 46 | // Select an item by its assigned value. 47 | Panel.SetListValue("lbUserAge", UserAge[UserAgeIndex]); 48 | UserAgeIndex = (UserAgeIndex + 1) % UserAgeCount; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Formatting.h: -------------------------------------------------------------------------------- 1 | /* *********************************************************************** 2 | * Format helpers for outputing values. 3 | * *********************************************************************** */ 4 | #pragma once 5 | 6 | #include 7 | 8 | #if !defined(typeof) 9 | #define typeof(x) __typeof__(x) 10 | #endif 11 | 12 | #define AsHex(x) AsHexWrapper(x) 13 | #define WithPrecision(x, p) WithPrecisionWrapper(x, p) 14 | 15 | template 16 | class AsHexWrapper : public Printable 17 | { 18 | private: 19 | TValue m_Value; 20 | 21 | public: 22 | 23 | AsHexWrapper(TValue Value) 24 | : m_Value(Value) 25 | { 26 | } 27 | 28 | virtual size_t printTo(Print& p) const override 29 | { 30 | return p.print(m_Value, HEX); 31 | } 32 | }; 33 | 34 | template 35 | class WithPrecisionWrapper : public Printable 36 | { 37 | private: 38 | TValue m_Value; 39 | uint8_t m_uPrecision; 40 | 41 | public: 42 | WithPrecisionWrapper(TValue Value, uint8_t uPrecision) 43 | { 44 | m_Value = Value; 45 | m_uPrecision = uPrecision; 46 | } 47 | 48 | virtual size_t printTo(Print& p) const override 49 | { 50 | return p.print(m_Value, m_uPrecision); 51 | } 52 | }; 53 | 54 | 55 | #define DECODE_BAD_DATA -1 56 | int DecodeFromBase64(Print& rDestination, const char* pchData); 57 | uint16_t CalculateChecksumFromBase64(const char* pchData); 58 | 59 | void EncodeAsBase64(Print& rDestination, const uint8_t* pData, uint16_t Length); 60 | 61 | void WriteHex(Print& rDestination, uint8_t uValue); 62 | void WriteHex(Print& rDestination, uint16_t uValue); 63 | void WriteHex(Print& rDestination, uint32_t uValue); 64 | 65 | -------------------------------------------------------------------------------- /examples/InterfacePanel/SendToMLP/SendToMLP.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program to set values on a MegunoLink Pro User Interface 3 | * Panel. Visit http://www.megunolink.com/how-to-update-interface-panel-controls-from-the-arduino/ 4 | * for more information. 5 | * 6 | * This program sends out commands to set the value of a progress bar named 'Progress', a 7 | * numeric up/down control named 'Current' and a text box named 'Status' periodically. The 8 | * interface panel is included in the MegunoLink Pro project in the example folder. 9 | * ********************************************************************************************** */ 10 | 11 | #include "MegunoLink.h" // Helpful functions for communicating with MegunoLink Pro. 12 | 13 | // Millis value when the data was last sent. 14 | long LastSent; 15 | 16 | // Progress value 17 | int Progress; 18 | 19 | // The interface panel we are sending data to 20 | InterfacePanel Panel; 21 | 22 | void setup() 23 | { 24 | Serial.begin(9600); 25 | 26 | LastSent = millis(); 27 | Progress = 0; 28 | } 29 | 30 | void loop() 31 | { 32 | if ((millis() - LastSent) > 1000) 33 | { 34 | LastSent = millis(); 35 | 36 | Panel.SetProgress("Progress", Progress); 37 | Panel.SetNumber("Current", Progress); 38 | 39 | if (Progress == 0) 40 | Panel.SetText("Status", "Start"); 41 | else if (Progress == 8) 42 | Panel.SetText("Status", "Nearly there"); 43 | else if (Progress == 9) 44 | Panel.SetText("Status", "End"); 45 | else 46 | Panel.SetText("Status", "Working"); 47 | 48 | Progress = (Progress + 1) % 10; 49 | } 50 | } -------------------------------------------------------------------------------- /src/Filter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | * Implements a simple linear recursive exponential filter. 5 | * See: http://www.statistics.com/glossary&term_id=756 */ 6 | template class ExponentialFilter 7 | { 8 | // Weight for new values, as a percentage ([0..100]) 9 | T m_WeightNew; 10 | 11 | // Current filtered value. 12 | T m_Current; 13 | 14 | public: 15 | ExponentialFilter(T WeightNew, T Initial) 16 | : m_WeightNew(WeightNew), m_Current(Initial*100) 17 | { } 18 | 19 | void Filter(T New) 20 | { 21 | m_Current = (100 * m_WeightNew * New + (100 - m_WeightNew) * m_Current + 50)/100; 22 | } 23 | 24 | void SetWeight(T NewWeight) 25 | { 26 | m_WeightNew = NewWeight; 27 | } 28 | 29 | T GetWeight() const { return m_WeightNew; } 30 | 31 | T Current() const { return (m_Current + 50)/100; } 32 | 33 | void SetCurrent(T NewValue) 34 | { 35 | m_Current = NewValue*100; 36 | } 37 | }; 38 | 39 | // Specialization for floating point math. 40 | template<> class ExponentialFilter 41 | { 42 | float m_fWeightNew; 43 | float m_fCurrent; 44 | 45 | public: 46 | ExponentialFilter(float fWeightNew, float fInitial) 47 | : m_fWeightNew(fWeightNew/100.0), m_fCurrent(fInitial) 48 | { } 49 | 50 | 51 | void Filter(float fNew) 52 | { 53 | m_fCurrent = m_fWeightNew * fNew + (1.0 - m_fWeightNew) * m_fCurrent; 54 | } 55 | 56 | void SetWeight(float NewWeight) 57 | { 58 | m_fWeightNew = NewWeight/100.0; 59 | } 60 | 61 | float GetWeight() const { return m_fWeightNew*100.0; } 62 | 63 | float Current() const { return m_fCurrent; } 64 | 65 | void SetCurrent(float fNewValue) 66 | { 67 | m_fCurrent = fNewValue; 68 | } 69 | }; 70 | 71 | -------------------------------------------------------------------------------- /src/utility/RecordTable.cpp: -------------------------------------------------------------------------------- 1 | #include "RecordTable.h" 2 | 3 | RecordTable::RecordTable(const char *Channel /*= NULL*/, Print &rDestination /*= Serial*/) 4 | : MegunoLinkProtocol(F("RECTBL"), Channel, rDestination) 5 | { 6 | m_nNumberOfDecimalPlaces = 3; 7 | } 8 | 9 | RecordTable::RecordTable(const __FlashStringHelper* Channel, Print& rDestination /*= Serial*/) 10 | : MegunoLinkProtocol(F("RECTBL"), Channel, rDestination) 11 | { 12 | m_nNumberOfDecimalPlaces = 3; 13 | } 14 | 15 | RecordTable::RecordTable(Print& rDestination) 16 | : MegunoLinkProtocol(F("RECTBL"), (const char*)NULL, rDestination) 17 | { 18 | m_nNumberOfDecimalPlaces = 3; 19 | } 20 | 21 | void RecordTable::ClearAllRows() 22 | { 23 | SendDataHeader(F("CLEAR")); 24 | SendDataTail(); 25 | } 26 | 27 | void RecordTable::ClearRow(int RowNumber) 28 | { 29 | SendDataHeader(F("CLEAR")); 30 | m_rDestination.print(RowNumber); 31 | SendDataTail(); 32 | } 33 | 34 | void RecordTable::SendHeader_Add() 35 | { 36 | SendDataHeader(F("ADD")); 37 | } 38 | 39 | void RecordTable::SendHeader_AddWithIds() 40 | { 41 | SendDataHeader(F("ADI")); 42 | } 43 | 44 | void RecordTable::SendHeader_Update() 45 | { 46 | SendDataHeader(F("SET")); 47 | } 48 | 49 | void RecordTable::SendHeader_UpdateWithIds() 50 | { 51 | SendDataHeader(F("STI")); 52 | } 53 | 54 | void RecordTable::SendHeader_SetValue() 55 | { 56 | SendDataHeader(F("STC")); 57 | } 58 | 59 | void RecordTable::SendColumnIds(int NumberOfIds, const uint8_t* pColumnIds) 60 | { 61 | while (NumberOfIds--) 62 | { 63 | m_rDestination.print(*pColumnIds++); 64 | if (NumberOfIds > 0) 65 | { 66 | m_rDestination.print(','); 67 | } 68 | } 69 | m_rDestination.print('='); 70 | } -------------------------------------------------------------------------------- /examples/InterfacePanel/MoveMotor/MoveMotor.ino: -------------------------------------------------------------------------------- 1 | /* ************************************************************************ 2 | Move Motor 3 | This program demonstrates how MegunoLink's Interface Panel and our command 4 | handler Arduino library can be used to control a stepper motor. 5 | 6 | The example folder also contains a MegunoLink project, with an Interface 7 | Panel to control the motor. 8 | Visit: 9 | * http://www.MegunoLink.com to download MegunoLink. 10 | ************************************************************************ */ 11 | #include "CommandHandler.h" 12 | 13 | CommandHandler<> SerialCommands; 14 | 15 | const int PinA = 7; 16 | const int PinB = 6; 17 | 18 | void setup() 19 | { 20 | pinMode(PinA, OUTPUT); 21 | pinMode(PinB, OUTPUT); 22 | Stop(); 23 | 24 | Serial.begin(9600); 25 | Serial.println("Motor Mover"); 26 | 27 | SerialCommands.AddCommand(F("Forward"), Cmd_Forward); 28 | SerialCommands.AddCommand(F("Reverse"), Cmd_Reverse); 29 | SerialCommands.AddCommand(F("Stop"), Cmd_Stop); 30 | } 31 | 32 | void loop() 33 | { 34 | SerialCommands.Process(); 35 | 36 | } 37 | 38 | void Stop() 39 | { 40 | digitalWrite(PinA, LOW); 41 | digitalWrite(PinB, LOW); 42 | } 43 | 44 | void Move(bool Forward) 45 | { 46 | if (Forward) 47 | { 48 | digitalWrite(PinA, LOW); 49 | digitalWrite(PinB, HIGH); 50 | } 51 | else 52 | { 53 | digitalWrite(PinA, HIGH); 54 | digitalWrite(PinB, LOW); 55 | } 56 | } 57 | 58 | void Cmd_Forward(CommandParameter &p) 59 | { 60 | Serial.println("Forward!"); 61 | Move(true); 62 | } 63 | 64 | void Cmd_Reverse(CommandParameter &p) 65 | { 66 | Serial.println("Reverse!"); 67 | Move(false); 68 | } 69 | 70 | void Cmd_Stop(CommandParameter &p) 71 | { 72 | Serial.println("Whoa!"); 73 | Stop(); 74 | } 75 | 76 | -------------------------------------------------------------------------------- /src/utility/Map.cpp: -------------------------------------------------------------------------------- 1 | #include "Map.h" 2 | 3 | 4 | Map::Map(Print &rDestination ) 5 | : MegunoLinkProtocol(F("MAP"), rDestination) 6 | { 7 | } 8 | 9 | Map::Map(const char* channelName, Print& rDestination) 10 | : MegunoLinkProtocol(F("MAP"), channelName, rDestination) 11 | { 12 | 13 | } 14 | 15 | Map::Map(const __FlashStringHelper* channelName, Print& rDestination) 16 | : MegunoLinkProtocol(F("MAP"), channelName, rDestination) 17 | { 18 | 19 | } 20 | 21 | void Map::SendData(const char *Placename, const char *Latitude, const char *Longitude) 22 | { 23 | SendDataHeader(F("SET")); 24 | m_rDestination.print(Placename); 25 | m_rDestination.print('|'); 26 | m_rDestination.print(Latitude); 27 | m_rDestination.print('|'); 28 | m_rDestination.print(Longitude); 29 | SendDataTail(); 30 | } 31 | 32 | void Map::SendData(const __FlashStringHelper *Placename, const char *Latitude, const char *Longitude) 33 | { 34 | SendDataHeader(F("SET")); 35 | m_rDestination.print(Placename); 36 | m_rDestination.print('|'); 37 | m_rDestination.print(Latitude); 38 | m_rDestination.print('|'); 39 | m_rDestination.print(Longitude); 40 | SendDataTail(); 41 | } 42 | 43 | void Map::SendData(const char *Placename, float Latitude, float Longitude) 44 | { 45 | SendDataHeader(F("SET")); 46 | m_rDestination.print(Placename); 47 | m_rDestination.print('|'); 48 | m_rDestination.print(Latitude, 7); 49 | m_rDestination.print('|'); 50 | m_rDestination.print(Longitude, 7); 51 | SendDataTail(); 52 | } 53 | 54 | void Map::SendData(const __FlashStringHelper *Placename, float Latitude, float Longitude) 55 | { 56 | SendDataHeader(F("SET")); 57 | m_rDestination.print(Placename); 58 | m_rDestination.print('|'); 59 | m_rDestination.print(Latitude, 7); 60 | m_rDestination.print('|'); 61 | m_rDestination.print(Longitude, 7); 62 | SendDataTail(); 63 | } 64 | 65 | -------------------------------------------------------------------------------- /examples/RecordTable/SendArray/SendArray.ino: -------------------------------------------------------------------------------- 1 | /* ************************************************************************ 2 | Send an array of data to a MegunoLink Record Table 3 | This example demonstrates sending an array of data read from the Arduino 4 | analog inputs to a MegunoLink Record Table. The analog measurements will 5 | be random unless you connect sensors to the analog inputs. 6 | 7 | The MegunoLink project for this example is in the same folder as this 8 | Arduino code. To download a free MegunoLink trial, visit: 9 | - http://www.MegunoLink.com to download MegunoLink. 10 | 11 | More Information 12 | - https://www.megunolink.com/documentation/table/record-table/ 13 | - https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 14 | ************************************************************************ */ 15 | 16 | #include "MegunoLink.h" 17 | #include "ArduinoTimer.h" 18 | 19 | RecordTable MyTable; 20 | ::ArduinoTimer SendDataTimer; 21 | 22 | void setup() 23 | { 24 | Serial.begin(115200); 25 | delay(1000); 26 | 27 | Serial.print("MegunoLink Record Table Array Example\n\n\n"); 28 | } 29 | 30 | void loop() 31 | { 32 | if (SendDataTimer.TimePassed_Milliseconds(5000)) 33 | { 34 | const int NumberOfChannels = 4; 35 | int Measurements[NumberOfChannels]; 36 | 37 | // Read the analog inputs. 38 | for(int Channel = 0; Channel < NumberOfChannels; ++Channel) 39 | { 40 | // Read analog sensor twice with a small delay to allow 41 | // the analog input to stabilize after the multiplexer 42 | // switches to a new channel. See: 43 | // https://forum.arduino.cc/index.php?topic=54976.0 44 | analogRead(Channel); 45 | delay(10); 46 | Measurements[Channel] = analogRead(Channel); 47 | } 48 | 49 | MyTable.AddRowFromArray(NumberOfChannels, Measurements); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /examples/CommandHandler/ESP32BlueTooth/ESP32BlueTooth.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | In this example we demonstrate our command handler for processing commands sent over the ESP32's 4 | Bluetooth connection. 5 | 6 | More Information 7 | * https://www.megunolink.com/documentation/getting-started-process-serial-commands/ 8 | * https://www.megunolink.com/documentation/arduino-libraries/serial-command-handler/ 9 | 10 | This Example Requires: 11 | * The MegunoLink arduino library https://www.megunolink.com/documentation/arduino-integration/ 12 | * The Pstring Library http://arduiniana.org/libraries/pstring/ 13 | * The EtherCard Library https://github.com/njh/EtherCard. 14 | 15 | MegunoLink Interface 16 | You can download a pre-made interface from here: 17 | https://github.com/Megunolink/MLP/raw/master/examples/CommandHandler/ESP32BlueTooth/ESP32BlueTooth.mlpz 18 | 19 | You can find out more about MegunoLink and download a free trial from here 20 | https://www.megunolink.com/ 21 | https://www.megunolink.com/download/ 22 | ************************************************************************************************/ 23 | 24 | /* To connect with the ESP32 in windows, open the Settings application; 25 | choose Devices and Add Bluetooth or other device. */ 26 | 27 | #include "BluetoothSerial.h" 28 | #include "CommandHandler.h" 29 | #include "ArduinoTimer.h" 30 | 31 | BluetoothSerial SerialBT; 32 | CommandHandler<> Cmds(SerialBT); 33 | 34 | void Cmd_ConnectionColor(CommandParameter &p) 35 | { 36 | SerialBT.println("Blue"); 37 | } 38 | 39 | void setup() 40 | { 41 | Serial.begin(9600); 42 | Serial.println("Serial Bluetooth test"); 43 | SerialBT.begin("ESP32"); 44 | Cmds.AddCommand(F("GetConnectionColor"), Cmd_ConnectionColor); 45 | } 46 | 47 | void loop() 48 | { 49 | Cmds.Process(); 50 | } 51 | -------------------------------------------------------------------------------- /src/utility/XYPlot.cpp: -------------------------------------------------------------------------------- 1 | #include "XYPlot.h" 2 | 3 | 4 | XYPlot::XYPlot(Print& rDestination) 5 | : Plot(F("XYPLOT"), rDestination) 6 | { 7 | } 8 | 9 | XYPlot::XYPlot(const char* channelName, Print& rDestination) 10 | : Plot(F("XYPLOT"), channelName, rDestination) 11 | { 12 | } 13 | 14 | XYPlot::XYPlot( const __FlashStringHelper *channelName, Print &rDestination ) 15 | : Plot(F("XYPLOT"), channelName, rDestination) 16 | { 17 | } 18 | 19 | #if 0 20 | void XYPlot::SendData(const __FlashStringHelper * seriesName, float *xValues, float *yValues, unsigned NumberOfValues, int nDecimalPlaces, const char * seriesProperties /*= NULL*/) 21 | { 22 | SendHeader_Data(); 23 | m_rDestination.print(seriesName); 24 | SendData(xValues, yValues, NumberOfValues, nDecimalPlaces, seriesProperties); 25 | } 26 | 27 | void XYPlot::SendData(const char * seriesName, float *xValues, float *yValues, unsigned NumberOfValues, int nDecimalPlaces, const char * seriesProperties /*= NULL*/) 28 | { 29 | SendHeader_Data(); 30 | m_rDestination.print(seriesName); 31 | SendData(xValues, yValues, NumberOfValues, nDecimalPlaces, seriesProperties); 32 | } 33 | 34 | void XYPlot::SendData(float *xValues, float *yValues, unsigned NumberOfValues, int nDecimalPlaces, const char * seriesProperties /*= NULL*/) 35 | { 36 | SendSeriesProperties(seriesProperties); 37 | while (NumberOfValues--) 38 | { 39 | m_rDestination.print(*xValues++, nDecimalPlaces); 40 | m_rDestination.print('|'); 41 | m_rDestination.print(*yValues++, nDecimalPlaces); 42 | if (NumberOfValues != 0) 43 | { 44 | m_rDestination.print('|'); 45 | } 46 | } 47 | SendDataTail(); 48 | } 49 | #endif 50 | 51 | 52 | void XYPlot::SetXRange(float fXLimMin, float fXlimMax) 53 | { 54 | SendDataHeader(F("xrange")); 55 | m_rDestination.print(fXLimMin, 5); 56 | m_rDestination.print("|"); 57 | m_rDestination.print(fXlimMax, 5); 58 | SendDataTail(); 59 | } -------------------------------------------------------------------------------- /src/MegunoLinkBufferWrapper.h: -------------------------------------------------------------------------------- 1 | /* *********************************************************************** 2 | * MegunoLinkBufferWrapper 3 | * Provides a mechanism to access MegunoLink classes that send commands 4 | * and data to visualizers from a shared destination. 5 | * *********************************************************************** */ 6 | 7 | #pragma once 8 | #include "Print.h" 9 | #include "MegunoLink.h" 10 | 11 | 12 | class MegunoLinkBufferWrapper 13 | { 14 | private: 15 | Print& m_rDestinationBuffer; 16 | 17 | public: 18 | MegunoLinkBufferWrapper(Print* pDestinationBuffer); 19 | 20 | TimePlot GetTimePlot(__FlashStringHelper const* channelName); 21 | TimePlot GetTimePlot(char const* channelName); 22 | TimePlot GetTimePlot(); 23 | 24 | XYPlot GetXYPlot(__FlashStringHelper const* channelName); 25 | XYPlot GetXYPlot(char const* channelName); 26 | XYPlot GetXYPlot(); 27 | 28 | InterfacePanel GetInterfacePanel(__FlashStringHelper const* channelName); 29 | InterfacePanel GetInterfacePanel(char const* channelName); 30 | InterfacePanel GetInterfacePanel(); 31 | 32 | Map GetMap(__FlashStringHelper const* channelName); 33 | Map GetMap(char const* channelName); 34 | Map GetMap(); 35 | 36 | Message GetMessage(__FlashStringHelper const* channelName); 37 | Message GetMessage(char const* channelName); 38 | Message GetMessage(); 39 | 40 | Table GetTable(__FlashStringHelper const* channelName); 41 | Table GetTable(char const* channelName); 42 | Table GetTable(); 43 | 44 | RecordTable GetRecordTable(__FlashStringHelper const* channelName); 45 | RecordTable GetRecordTable(char const* channelName); 46 | RecordTable GetRecordTable(); 47 | 48 | Monkey GetMonkey(__FlashStringHelper const* channelName); 49 | Monkey GetMonkey(char const* channelName); 50 | Monkey GetMonkey(); 51 | 52 | Report GetReport(); 53 | Audio GetAudio(); 54 | Pushover GetPushover(); 55 | 56 | }; -------------------------------------------------------------------------------- /examples/InterfacePanel/SingleMessageMultipleParameters/SingleMessageMultipleParameters.ino: -------------------------------------------------------------------------------- 1 | /* ************************************************************************ 2 | Single Message Multiple Parameters 3 | This program demonstrates how MegunoLink's Interface Panel and our command 4 | handler Arduino library can be used to update multiple variables using a 5 | single message. 6 | 7 | The example folder also contains a MegunoLink project, with an Interface 8 | Panel to update the variables. 9 | Visit: 10 | * http://www.MegunoLink.com to download MegunoLink. 11 | ************************************************************************ */ 12 | 13 | #include "MegunoLink.h" 14 | #include "CommandHandler.h" 15 | 16 | 17 | float a = 1; 18 | float b = 2; 19 | float c = 3; 20 | 21 | CommandHandler<> SerialCommandHandler; 22 | InterfacePanel MyInterface; 23 | 24 | void Cmd_GetValues(CommandParameter &Parameters) 25 | { 26 | Serial.println("\nSending values to interface."); 27 | MyInterface.SetNumber(F("a"), a); 28 | MyInterface.SetNumber(F("b"), b); 29 | MyInterface.SetNumber(F("c"), c); 30 | } 31 | 32 | void Cmd_SetValues(CommandParameter &Parameters) 33 | { 34 | Serial.print("\nUpdating values.."); 35 | a = Parameters.NextParameterAsDouble(); 36 | b = Parameters.NextParameterAsDouble(); 37 | c = Parameters.NextParameterAsDouble(); 38 | 39 | Serial.print(" a = "); Serial.print(a); 40 | Serial.print(" b = "); Serial.print(b); 41 | Serial.print(" c = "); Serial.println(c); 42 | } 43 | 44 | void setup() 45 | { 46 | Serial.begin(9600); 47 | delay(1000); 48 | Serial.println("Single Message Multiple Parameter Example"); 49 | Serial.println("------------------------------------------"); 50 | 51 | SerialCommandHandler.AddCommand(F("SetValues"), Cmd_SetValues); 52 | SerialCommandHandler.AddCommand(F("GetValues"), Cmd_GetValues); 53 | 54 | } 55 | 56 | void loop() 57 | { 58 | SerialCommandHandler.Process(); 59 | } -------------------------------------------------------------------------------- /src/utility/MegunoLinkProtocol.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | enum class SpecialParameters 5 | { 6 | CurrentTime 7 | }; 8 | 9 | class MegunoLinkProtocol 10 | { 11 | // A string in flash memory on boards that support this. 12 | PGM_P m_pfchContext; 13 | 14 | const void *m_ChannelName; 15 | const bool m_bFlashString; 16 | 17 | protected: 18 | Print &m_rDestination; 19 | 20 | protected: 21 | MegunoLinkProtocol(const __FlashStringHelper *Context); 22 | MegunoLinkProtocol(const __FlashStringHelper *Context, const char *Channel); 23 | MegunoLinkProtocol(const __FlashStringHelper *Context, const __FlashStringHelper *Channel); 24 | 25 | MegunoLinkProtocol(const __FlashStringHelper *Context, Print &rDestination); 26 | MegunoLinkProtocol(const __FlashStringHelper *Context, const char *Channel, Print &rDestination); 27 | MegunoLinkProtocol(const __FlashStringHelper *Context, const __FlashStringHelper *Channel, Print &rDestination); 28 | 29 | void SendDataHeader(const __FlashStringHelper* pfstrCommand, bool bIncludeSeparator = true); 30 | void SendDataHeader(const char* pfstrCommand, bool bIncludeSeparator = true); 31 | void SendDataTail(); 32 | 33 | // Some boards don't put strings into flash. They redefine F() macro 34 | // as empty, which causes these overrides to be called. Here we assume 35 | // if this override is called then the context is not a flash string either. 36 | MegunoLinkProtocol(const char* Context); 37 | MegunoLinkProtocol(const char* Context, const char* Channel); 38 | MegunoLinkProtocol(const char* Context, const __FlashStringHelper* Channel); 39 | 40 | MegunoLinkProtocol(const char* Context, Print& rDestination); 41 | MegunoLinkProtocol(const char* Context, const char* Channel, Print& rDestination); 42 | MegunoLinkProtocol(const char* Context, const __FlashStringHelper* Channel, Print& rDestination); 43 | 44 | void SendValue(SpecialParameters p); 45 | 46 | 47 | public: 48 | void Attach(Print& rDestination); 49 | 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /src/utility/Pushover.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MegunoLinkProtocol.h" 3 | 4 | class Pushover : public MegunoLinkProtocol 5 | { 6 | public: 7 | 8 | enum EPriority 9 | { 10 | DefaultPriority = 0, 11 | 12 | LowestPriority = 1, 13 | 14 | LowPriority = 2, 15 | 16 | NormalPriority = 3, 17 | 18 | HighPriority = 4, 19 | 20 | EmergencyPriority = 5, 21 | }; 22 | 23 | enum ENotificationSound 24 | { 25 | DefaultSound = 0, // will leave empty on sending 26 | PushoverSound = 1, 27 | BikeSound = 2, 28 | BugleSound = 3, 29 | CashRegisterSound = 4, 30 | ClassicalSound = 5, 31 | CosmicSound = 6, 32 | FallingSound = 7, 33 | GamelanSound = 8, 34 | IncomingSound = 9, 35 | IntermissionSound = 10, 36 | MagicSound = 11, 37 | MechanicalSound = 12, 38 | PianobarSound = 13, 39 | SirenSound = 14, 40 | SpaceAlarmSound = 15, 41 | TugboatSound = 16, 42 | AlienSound = 17, 43 | ClimbSound = 18, 44 | PersistentSound = 19, 45 | EchoSound = 20, 46 | UpdownSound = 21, 47 | NoSound = 22, 48 | }; 49 | 50 | public: 51 | Pushover(Print& rDestination = Serial); 52 | 53 | template void Send(TContent Content) 54 | { 55 | SendDataHeader(F("SND")); 56 | m_rDestination.print(Content); 57 | SendDataTail(); 58 | } 59 | 60 | template void Send(TContent Content, ENotificationSound Sound) 61 | { 62 | SendDataHeader(F("SND")); 63 | m_rDestination.print(Content); 64 | m_rDestination.print('|'); 65 | m_rDestination.print((int)Sound); 66 | SendDataTail(); 67 | } 68 | 69 | template void Send(TContent Content, ENotificationSound Sound, EPriority Priority) 70 | { 71 | SendDataHeader(F("SND")); 72 | m_rDestination.print(Content); 73 | m_rDestination.print('|'); 74 | m_rDestination.print((int)Sound); 75 | m_rDestination.print('|'); 76 | m_rDestination.print((int)Priority); 77 | SendDataTail(); 78 | } 79 | 80 | private: 81 | }; -------------------------------------------------------------------------------- /src/utility/TestReport.cpp: -------------------------------------------------------------------------------- 1 | #include "TestReport.h" 2 | 3 | TestReport::TestReport(Print & rDestination) 4 | : MegunoLinkProtocol(F("TEST"), rDestination) 5 | { 6 | } 7 | 8 | void TestReport::ReportResult(int TestId, bool bPass) 9 | { 10 | SendFirstPart(bPass, TestId); 11 | SendDataTail(); 12 | } 13 | 14 | void TestReport::ReportResult(const char * pchName, bool bPass) 15 | { 16 | SendFirstPart(bPass, pchName); 17 | SendDataTail(); 18 | } 19 | 20 | void TestReport::ReportResult(const __FlashStringHelper * pchName, bool bPass) 21 | { 22 | SendFirstPart(bPass, pchName); 23 | SendDataTail(); 24 | } 25 | 26 | void TestReport::Pass(const char * pchName) 27 | { 28 | SendFirstPart(true, pchName); 29 | SendDataTail(); 30 | } 31 | 32 | void TestReport::Pass(const __FlashStringHelper * pchName) 33 | { 34 | SendFirstPart(true, pchName); 35 | SendDataTail(); 36 | } 37 | 38 | void TestReport::Fail(const char * pchName) 39 | { 40 | SendFirstPart(false, pchName); 41 | SendDataTail(); 42 | } 43 | 44 | void TestReport::Fail(const __FlashStringHelper * pchName) 45 | { 46 | SendFirstPart(false, pchName); 47 | SendDataTail(); 48 | } 49 | 50 | void TestReport::StartingTest() 51 | { 52 | SendDataHeader(F("START")); 53 | SendDataTail(); 54 | } 55 | 56 | void TestReport::TestComplete() 57 | { 58 | SendDataHeader(F("DONE")); 59 | SendDataTail(); 60 | } 61 | 62 | void TestReport::SendFirstPart(bool bPass, const char * pchName) 63 | { 64 | SendFirstPart(bPass); 65 | m_rDestination.print(pchName); 66 | } 67 | 68 | void TestReport::SendFirstPart(bool bPass, const __FlashStringHelper * pchName) 69 | { 70 | SendFirstPart(bPass); 71 | m_rDestination.print(pchName); 72 | } 73 | 74 | void TestReport::SendFirstPart(bool bPass, int nTestId) 75 | { 76 | SendFirstPart(bPass); 77 | m_rDestination.print(nTestId); 78 | } 79 | 80 | void TestReport::SendFirstPart(bool bPass) 81 | { 82 | if (bPass) 83 | { 84 | SendDataHeader(F("PASS")); 85 | } 86 | else 87 | { 88 | SendDataHeader(F("FAIL")); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/UdpManager.cpp: -------------------------------------------------------------------------------- 1 | #include "UdpManager.h" 2 | 3 | UdpManager::UdpManager(UDP &rConnection, uint16_t uListenPort, uint16_t uDestinationPort) 4 | : m_uListenPort(uListenPort) 5 | , m_rConnection(rConnection) 6 | { 7 | m_uDefaultDestinationPort = uDestinationPort == 0 ? uListenPort : uDestinationPort; 8 | SetDefaultDestinationToBroadcast(); 9 | } 10 | 11 | bool UdpManager::OnNetworkConnected() 12 | { 13 | if (!m_rConnection.begin(m_uListenPort)) 14 | { 15 | Serial.println(F("ERR: UDP listen")); 16 | return false; 17 | } 18 | 19 | return true; 20 | } 21 | 22 | void UdpManager::OnNetworkConnectionLost() 23 | { 24 | m_rConnection.stop(); 25 | } 26 | 27 | void UdpManager::SetDefaultDestinationPort(uint16_t uDestinationPort) 28 | { 29 | m_uDefaultDestinationPort = uDestinationPort; 30 | } 31 | 32 | void UdpManager::SetDefaultDestination(IPAddress DestinationAddress, uint16_t uDestinationPort) 33 | { 34 | m_DefaultDestinationAddress = DestinationAddress; 35 | if (uDestinationPort != 0) 36 | { 37 | m_uDefaultDestinationPort = uDestinationPort; 38 | } 39 | } 40 | 41 | void UdpManager::SetDefaultDestinationToBroadcast() 42 | { 43 | m_DefaultDestinationAddress = IPAddress(255, 255, 255, 255); 44 | } 45 | 46 | bool UdpManager::SendBlock(const char* pchData, size_t szLength) 47 | { 48 | return SendBlock(pchData, szLength, m_DefaultDestinationAddress, m_uDefaultDestinationPort); 49 | } 50 | 51 | bool UdpManager::SendBlock(const char* pchData, size_t szLength, IPAddress DestinationAddress, uint16_t uDestinationPort) 52 | { 53 | if ((uint32_t)DestinationAddress == 0) 54 | { 55 | DestinationAddress = m_DefaultDestinationAddress; 56 | } 57 | 58 | if (uDestinationPort == 0) 59 | { 60 | uDestinationPort = m_uDefaultDestinationPort; 61 | } 62 | 63 | if (!m_rConnection.beginPacket(DestinationAddress, uDestinationPort)) 64 | { 65 | return false; 66 | } 67 | 68 | if (m_rConnection.write((uint8_t*)pchData, szLength) != szLength) 69 | { 70 | return false; 71 | } 72 | 73 | return m_rConnection.endPacket() != 0; 74 | } 75 | -------------------------------------------------------------------------------- /examples/InterfacePanel/HandlingStrings/HandlingStrings.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | In this example we demonstrate how to handle strings with our command handler. This is great if 4 | you want to be able to send your device a password or SSID to establish a network connection or 5 | maybe adjust some text on a display. 6 | 7 | More Information 8 | * https://www.megunolink.com/documentation/build-arduino-interface/ 9 | * https://www.megunolink.com/documentation/interface-panel/ 10 | * https://www.megunolink.com/documentation/arduino-libraries/serial-command-handler/ 11 | 12 | This Example Requires: 13 | * The MegunoLink library for Arduino https://www.megunolink.com/documentation/arduino-integration/ 14 | 15 | MegunoLink Interface 16 | You can download a pre-made interface from here: 17 | https://github.com/Megunolink/MLP/raw/master/examples/InterfacePanel/HandlingStrings/HandlingStrings.mlpz 18 | 19 | You can find out more about MegunoLink and download a free trial from here 20 | https://www.megunolink.com/ 21 | https://www.megunolink.com/download/ 22 | ************************************************************************************************/ 23 | 24 | #include "MegunoLink.h" 25 | #include "CommandHandler.h" 26 | #include "FixedStringBuffer.h" 27 | 28 | CommandHandler<> SerialCommandHandler; 29 | 30 | void Cmd_SetSSID(CommandParameter &Parameters) 31 | { 32 | // Create local fixed size character buffer on the stack 33 | FixedStringBuffer<50> mystring; 34 | 35 | // Put the characters from MegunoLink into buffer 36 | mystring.print(Parameters.RemainingParameters()); 37 | 38 | Serial.print("NewSSID:"); 39 | Serial.println(mystring); 40 | } 41 | 42 | void setup() 43 | { 44 | Serial.begin(9600); 45 | Serial.println("MegunoLink - Handling Strings"); 46 | Serial.println("-----------------------------"); 47 | 48 | SerialCommandHandler.AddCommand(F("SetSSID"), Cmd_SetSSID); 49 | } 50 | 51 | void loop() 52 | { 53 | SerialCommandHandler.Process(); 54 | } 55 | -------------------------------------------------------------------------------- /src/FixedStringBuffer.h: -------------------------------------------------------------------------------- 1 | /* *********************************************************************** 2 | * FixedStringBuffer 3 | * Modelled off PString but Mikal Hart 4 | * http://arduiniana.org/libraries/pstring/ 5 | * *********************************************************************** */ 6 | #pragma once 7 | 8 | #include 9 | 10 | 11 | class FixedStringPrint : public Print 12 | { 13 | private: 14 | // start of buffer that we are writing to 15 | char* m_pchBuffer; 16 | 17 | // Maximum buffer size. 18 | size_t m_szBuffer; 19 | 20 | // Next location in buffer to write to 21 | char* m_pchNext; 22 | 23 | // True if we've tried to write more than can fit in the buffer. 24 | bool m_bBufferFlow; 25 | public: 26 | 27 | FixedStringPrint(char* pchBuffer, size_t szBuffer); 28 | 29 | void begin(); 30 | 31 | inline size_t length() const 32 | { 33 | return m_pchNext - m_pchBuffer; 34 | } 35 | 36 | inline size_t available() const 37 | { 38 | return capacity() - length(); 39 | } 40 | 41 | inline size_t capacity() const 42 | { 43 | return m_szBuffer; 44 | } 45 | 46 | bool operator==(char const* pchTest) const 47 | { 48 | return m_szBuffer > 0 && strcmp(m_pchBuffer, pchTest) == 0; 49 | } 50 | 51 | inline operator char const* () const 52 | { 53 | return m_pchBuffer; 54 | } 55 | 56 | inline char const* c_str() const 57 | { 58 | return m_pchBuffer; 59 | } 60 | 61 | template inline FixedStringPrint& operator=(T value) 62 | { 63 | begin(); 64 | print(value); 65 | return *this; 66 | } 67 | 68 | template inline FixedStringPrint& operator+=(T value) 69 | { 70 | print(value); 71 | return *this; 72 | } 73 | 74 | size_t write(uint8_t uValue) override; 75 | 76 | bool IsOverflow() const { return m_bBufferFlow; } 77 | }; 78 | 79 | 80 | template class FixedStringBuffer : public FixedStringPrint 81 | { 82 | private: 83 | char m_achBuffer[nBufferSize]; 84 | 85 | public: 86 | FixedStringBuffer() : FixedStringPrint(m_achBuffer, sizeof(m_achBuffer)) 87 | { 88 | } 89 | }; -------------------------------------------------------------------------------- /src/utility/Message.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MegunoLinkProtocol.h" 3 | 4 | class Message : public MegunoLinkProtocol 5 | { 6 | public: 7 | // Flags to select destination for messages 8 | enum MessageDestination 9 | { 10 | Text = 0x01, 11 | 12 | Speak = 0x02, 13 | 14 | TextAndSpeak = 0x03, 15 | }; 16 | 17 | private: 18 | 19 | const MessageDestination m_Destination; 20 | 21 | public: 22 | Message(Print& rDestination = Serial); 23 | Message(const char *channelName, Print &rDestination = Serial); 24 | Message(const __FlashStringHelper *channelName, Print &rDestination = Serial); 25 | 26 | Message(MessageDestination Destination, Print& rDestination = Serial); 27 | Message(MessageDestination Destination, const char* channelName, Print& rDestination = Serial); 28 | Message(MessageDestination Destination, const __FlashStringHelper *channelName, Print &rDestination = Serial); 29 | 30 | void Begin(); 31 | void End(); 32 | 33 | void Send(const char *Message); 34 | void Send(const __FlashStringHelper *Message); 35 | 36 | template void Send(TValue Value) 37 | { 38 | Begin(); 39 | m_rDestination.print(Value); 40 | SendDataTail(); 41 | } 42 | 43 | template void Send(long Time, TValue Value) 44 | { 45 | Begin(); 46 | m_rDestination.print(Time); 47 | SendSeparator(); 48 | m_rDestination.print(Value); 49 | SendDataTail(); 50 | } 51 | 52 | template void Send(const char *Label, TValue Value) 53 | { 54 | Begin(); 55 | m_rDestination.print(Label); 56 | SendSeparator(); 57 | m_rDestination.print(Value); 58 | SendDataTail(); 59 | } 60 | 61 | template void Send(const __FlashStringHelper *Label, TValue Value) 62 | { 63 | Begin(); 64 | m_rDestination.print(Label); 65 | SendSeparator(); 66 | m_rDestination.print(Value); 67 | SendDataTail(); 68 | } 69 | 70 | void Clear(); 71 | 72 | void LogTo(const __FlashStringHelper *Filename); 73 | void LogTo(String &Filename); 74 | void LogTo(const char *Filename); 75 | void StartLogging(); 76 | void StopLogging(); 77 | void Flush(); 78 | 79 | private: 80 | void SendSeparator(); 81 | }; 82 | 83 | -------------------------------------------------------------------------------- /examples/XYPlot/Lissajou/Lissajou.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program to plot a Lissajous curve on MegunoLink's X-Y Plot visualiser 3 | * Visit http://www.megunolink.com/documentation/plotting/ 4 | * for more information. 5 | * ********************************************************************************************** */ 6 | 7 | #include "MegunoLink.h" 8 | 9 | float t; 10 | double i=0; 11 | Plot::Colors PlotColors[] = {Plot::Red, Plot::Blue, Plot::Green}; 12 | const int NumberOfLineStyles = sizeof(PlotColors)/sizeof(PlotColors[0]); 13 | byte ColourIndex = 0; //Array index selecting current colour 14 | long LastColourChangeTime; 15 | 16 | XYPlot MyPlot("Lissajou"); 17 | 18 | void setup() 19 | { 20 | Serial.begin(9600); 21 | 22 | //Send Plot Title And Axis Labels To MegunoLink Pro 23 | MyPlot.SetTitle("Lissajou Plot"); 24 | MyPlot.SetXLabel("Xaxis Value"); 25 | MyPlot.SetYLabel("Yaxis Value"); 26 | 27 | // Set the plotting parameters. "Sinewave" = series name, Plot::Blue = line colour 28 | // 2 = line width, Plot::Square = marker style 29 | MyPlot.SetSeriesProperties("Lissajou", Plot::Blue, Plot::Solid, 2, Plot::Square); 30 | 31 | // Colours include 32 | // Red, Green, Blue, Yellow, Black, Magenta, Cyan, White 33 | 34 | // Markers include 35 | // Square, Diamond, Triangle, Circle, Cross, Plus, Star, DownwardTriangle, NoMarker 36 | 37 | // Line style 38 | // Solid, Dashed, Dotted, DashDot, DashDotDot 39 | 40 | t = 0; 41 | } 42 | 43 | void loop() 44 | { 45 | float x, y; 46 | 47 | x = sin(5 * t + 1.57); 48 | y = cos(4 * t); 49 | t = t + 0.03; 50 | 51 | //Send Plotting Data To MegunoLink Pro 52 | MyPlot.SendData(F("Lissajou"),x,y); // Lissajou = series name, x = xaxis value, y = yaxis value 53 | MyPlot.SetSeriesProperties("Lissajou", PlotColors[ColourIndex], Plot::Solid, 2, Plot::Square); 54 | 55 | if((millis()-LastColourChangeTime)>1500) //Every 1500ms change the colour 56 | { 57 | ++ColourIndex; 58 | if(ColourIndex >= NumberOfLineStyles) 59 | ColourIndex = 0; 60 | 61 | LastColourChangeTime = millis(); 62 | } 63 | 64 | 65 | 66 | delay(200); 67 | 68 | } 69 | 70 | -------------------------------------------------------------------------------- /examples/InitializingSettings/InitializingSettings.ino: -------------------------------------------------------------------------------- 1 | /* ****************************************************************** 2 | Example illustrating how to initialize graph appearance and interface 3 | panel controls with current configuration data when a serial 4 | connection is opened. 5 | 6 | The example folder also contains a MegunoLink project for this example. 7 | To download a free MegunoLink trial, visit: 8 | http://www.MegunoLink.com to download MegunoLink. 9 | 10 | More Information 11 | - https://www.megunolink.com/articles/how-do-i/sending-initial-settings/ 12 | - https://www.megunolink.com/documentation/getting-started/processing-serial-commands/ 13 | - https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 14 | 15 | */ 16 | #include "MegunoLink.h" 17 | #include "ArduinoTimer.h" 18 | #include "CommandHandler.h" 19 | 20 | // To process serial commands. 21 | CommandHandler<> SerialCmds; 22 | 23 | // For communicating with plot and interface panel visualizers. 24 | TimePlot Plot; 25 | InterfacePanel Panel; 26 | 27 | // To periodically send measurements. 28 | ::ArduinoTimer SendMeasurementsTimer; 29 | unsigned long UpdateInterval = 100; 30 | 31 | // Command handler to send settings when the 'SendConfig' 32 | // command is received. 33 | void Cmd_SendConfiguration(CommandParameter& p) 34 | { 35 | SendConfiguration(); 36 | } 37 | 38 | // Send current configuration to MegunoLink. 39 | void SendConfiguration() 40 | { 41 | Plot.SetTitle(F("My data")); 42 | Plot.SetXLabel(F("Measurement time")); 43 | Plot.SetYLabel(F("Voltage")); 44 | 45 | Panel.SetNumber(F("DataRate"), UpdateInterval); 46 | } 47 | 48 | // Setup communications and commands. 49 | void setup() 50 | { 51 | Serial.begin(9600); 52 | 53 | SerialCmds.AddCommand(F("SendConfig"), Cmd_SendConfiguration); 54 | SerialCmds.AddVariable(F("DataRate"), UpdateInterval); 55 | 56 | SendConfiguration(); 57 | } 58 | 59 | // Main loop. 60 | void loop() 61 | { 62 | // Receive and dispatch serial commands. 63 | SerialCmds.Process(); 64 | 65 | // Periodically send measurements to MegunoLink. 66 | if (SendMeasurementsTimer.TimePassed_Milliseconds(UpdateInterval)) 67 | { 68 | Plot.SendData(F("Battery"), analogRead(0)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /examples/InterfacePanel/ConfigurableOutputPin/ConfigurableOutputPin.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | This program demonstrates how MegunoLink's Interface Panel and our command 4 | handler Arduino library can be used to reconfigure which IO pin your device 5 | is using at runtime. 6 | 7 | More Information 8 | * https://www.megunolink.com/documentation/interface-panel/ 9 | 10 | This Example Requires: 11 | * The MegunoLink arduino library https://www.megunolink.com/documentation/arduino-integration/ 12 | 13 | MegunoLink Interface 14 | You can download a pre-made interface from here: 15 | https://github.com/Megunolink/MLP/raw/master/examples/InterfacePanel/ConfigurableOutputPin/ConfigurableOutputPin.mlpz 16 | 17 | You can find out more about MegunoLink and download a free trial from here 18 | https://www.megunolink.com/ 19 | https://www.megunolink.com/download/ 20 | ************************************************************************************************/ 21 | 22 | #include "MegunoLink.h" 23 | #include "CommandHandler.h" 24 | 25 | 26 | int IOPort = 9; //initial IO pin number 27 | 28 | long LastToggleTime = 0; // Time we last toggled the IO 29 | int OnTime = 10; // Amount of time the IO remains on [milliseconds] 30 | int OffTime = 100; // Amount of time the IO remains off [milliseconds] 31 | 32 | CommandHandler<> SerialCommandHandler; 33 | 34 | void Cmd_SetIOPin(CommandParameter &Parameters) 35 | { 36 | Serial.print("Setting IO Port to:"); 37 | IOPort = Parameters.NextParameterAsInteger(); 38 | pinMode(IOPort, OUTPUT); 39 | Serial.println(IOPort); 40 | } 41 | 42 | void setup() 43 | { 44 | Serial.begin(9600); 45 | Serial.println("Configurable IO Pin Demo"); 46 | Serial.println("-----------------------------"); 47 | 48 | pinMode(IOPort, OUTPUT); 49 | 50 | SerialCommandHandler.AddCommand(F("SetIOPin"), Cmd_SetIOPin); 51 | } 52 | 53 | void loop() 54 | { 55 | SerialCommandHandler.Process(); 56 | 57 | // Toggle the IO Pin 58 | uint32_t uNow = millis(); 59 | if (uNow - LastToggleTime < OnTime) 60 | digitalWrite(IOPort, HIGH); 61 | else 62 | digitalWrite(IOPort, LOW); 63 | 64 | if (uNow - LastToggleTime > OnTime + OffTime) 65 | LastToggleTime = uNow; 66 | } 67 | -------------------------------------------------------------------------------- /examples/MessageLogger/MultipleCSVLogFiles/MultipleCSVLogFiles.ino: -------------------------------------------------------------------------------- 1 | /* *********************************************************************** 2 | Example program to send CSV data through Megunolinks message system and 3 | log data to a text file based on a file name supplied as a parameter to 4 | the serial command which starts logging. 5 | 6 | The MegunoLink project for this example is in the same folder as this 7 | Arduino code. To download a free MegunoLink trial, visit: 8 | - http://www.MegunoLink.com to download MegunoLink. 9 | 10 | More Information 11 | - https://www.megunolink.com/documentation/logging/message-logger/ 12 | - https://www.megunolink.com/documentation/getting-started/processing-serial-commands/ 13 | - https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 14 | 15 | This example requires: 16 | - Our MegunoLink Arduino library 17 | https://www.megunolink.com/documentation/arduino-library/ 18 | * *********************************************************************** */ 19 | 20 | #include "MegunoLink.h" 21 | #include "CommandHandler.h" 22 | #include "ArduinoTimer.h" 23 | 24 | Message Msg; 25 | CommandHandler<> Cmds; 26 | ::ArduinoTimer ExperimentTimer; 27 | 28 | 29 | int SamplingPeriod = 10; 30 | uint32_t ExperimentStartTime = -SamplingPeriod * 1000; 31 | 32 | 33 | void Cmd_StartExperiment(CommandParameter &p) 34 | { 35 | SamplingPeriod = p.NextParameterAsInteger(); 36 | Msg.LogTo(p.RemainingParameters()); 37 | ExperimentStartTime = millis(); 38 | } 39 | 40 | void setup() 41 | { 42 | Serial.begin(9600); 43 | Cmds.AddCommand(F("Start"), Cmd_StartExperiment); 44 | 45 | } 46 | 47 | void loop() 48 | { 49 | Cmds.Process(); 50 | if ((millis() - ExperimentStartTime) < (SamplingPeriod * 1000)) 51 | { 52 | int Value1 = analogRead(A0); 53 | #if defined(A1) 54 | int Value2 = analogRead(A1); 55 | #else 56 | // Some boards only have 1 analog input. For them we'll get another value from the first port. 57 | int Value2 = analogRead(A0); 58 | #endif 59 | 60 | Msg.Begin(); 61 | Serial.print(millis() - ExperimentStartTime); //Milliseconds since run started 62 | Serial.print(","); 63 | Serial.print(Value1); 64 | Serial.print(","); 65 | Serial.print(Value2); 66 | Msg.End(); 67 | 68 | delay(100); 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /examples/Getting Started/SendToTable/SendToTable.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program to send data to a MegunoLink property table. Find the MegunoLink project 3 | * (Sinewave.mlpz), that goes with this exaple, in the same folder as this Arduino code file. 4 | * 5 | * For more information: 6 | * Property table visualizer reference: 7 | * https://www.megunolink.com/documentation/table/property-table/ 8 | * Installing the MegunoLink Arduino library: 9 | * https://www.megunolink.com/documentation/getting-started/arduino-integration/ 10 | * ArduinoTimer reference: 11 | * https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 12 | * ********************************************************************************************** */ 13 | 14 | #include "MegunoLink.h" // For communicating with MegunoLink 15 | #include "ArduinoTimer.h" // To periodically send data. 16 | 17 | // Progress value variables (the data we'll send) 18 | int Fish, Turtles; 19 | 20 | // To send data to MegunoLink property tables. For all the methods available, see: 21 | // https://www.megunolink.com/documentation/table/sending-data-to-the-property-table/ 22 | Table MyTable; 23 | 24 | // To keep track of when we should send data. 25 | // See: https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 26 | ::ArduinoTimer SendTimer; 27 | 28 | void setup() 29 | { 30 | Serial.begin(9600); 31 | Serial.println(F("Send to Property Table example")); 32 | Serial.println(F("------------------------------")); 33 | 34 | // Initialize data we're going to send. 35 | Fish = 0; 36 | Turtles = 0; 37 | 38 | // Add descriptions to the table. These can be included when sending data 39 | // too (see loop). 40 | MyTable.SetDescription("Fish", "Lives in the sea"); 41 | //MyTable.SetDescription("Turtles", "Very slow"); 42 | } 43 | 44 | void loop() 45 | { 46 | if (SendTimer.TimePassed_Milliseconds(1000)) 47 | { 48 | // Send values to MegunoLink table. 49 | MyTable.SendData("Fish", Fish); 50 | 51 | // The description can be included too 52 | MyTable.SendData("Turtles", Turtles, "Very slow"); 53 | 54 | // Update the data we're sending. 55 | Fish += 3; 56 | Turtles += 1; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/utility/DeviceFileTransfer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MegunoLinkProtocol.h" 3 | #include 4 | #include 5 | 6 | 7 | enum class DFTResult 8 | { 9 | Ok = 'k', 10 | 11 | // Command isn't recognized. 12 | UnknownCommand = '?', 13 | 14 | // Failed to open root folder either because 15 | // it doesn't exist or isn't a directory. 16 | BadRoot = 'r', 17 | 18 | // Seeking a file position failed. 19 | SeekFailed = 's', 20 | 21 | // Failed to open a file. The file might no longer 22 | // exist, or already be opened. 23 | FileOpenFailed = 'o', 24 | 25 | // The address for the datablock is not at the 26 | // end of the target file. 27 | BadDataBlockAddress = 'a', 28 | 29 | // A filename was too long. 30 | PathTooLong = 'l', 31 | 32 | // Received and calculated checksum didn't match. 33 | BadChecksum = '#', 34 | 35 | // Bad base-64 data received. 36 | BadData = '6', 37 | 38 | // File deletion is not permitted. 39 | FileDeleteDisabled = 'x', 40 | 41 | // Delete all files is disabled. 42 | DeleteAllDisabled = 'f', 43 | 44 | // Failed to delete file requested. 45 | DeleteFileFailed = 'e', 46 | 47 | // Unable to mount the SD card. 48 | SDMountFailed = 'm', 49 | 50 | // SD Card missing 51 | SDCardMissing = 'c', 52 | }; 53 | 54 | class DeviceFileTransfer : public MegunoLinkProtocol 55 | { 56 | public: 57 | DeviceFileTransfer(Print& rDestination = Serial); 58 | 59 | void SendFileInfo(const char* pchFilepath, uint32_t uFileLength, time_t ttLastModified); 60 | void SendFileBytes(const char* pchFilepath, uint32_t nFirstByte, uint8_t* pData, uint16_t uLength, bool bMore); 61 | void SendFileBytes(const char* pchFilePath, Stream& rSource, uint32_t uCurrentPosition, uint16_t uMaxLength); 62 | void SendFileBytes(const char* pchFilePath, uint32_t uCurrentPosition, DFTResult Result); 63 | 64 | void FileReceiveResult(const char* pchFilePath, uint32_t uStartAddress, int16_t nReceived, DFTResult Result); 65 | 66 | void FileDeleteResult(const char* pchFilePath, DFTResult Result); 67 | void AllFilesDeleted(uint16_t uRequestId, DFTResult Result); 68 | 69 | void ReportSDMountFailed(); 70 | void ReportCardMissing(); 71 | 72 | void SendError(DFTResult ErrorCode, char chOperation, const char* pchFilePath = nullptr, uint32_t uContext = 0); 73 | }; 74 | -------------------------------------------------------------------------------- /examples/InterfacePanel/RadioButtons/RadioButtons.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | In this example we process commands sent from MegunoLink when radio buttons on an Interface Panel 4 | change state. 5 | 6 | More Information 7 | * https://www.megunolink.com/documentation/interface-panel/ 8 | 9 | This Example Requires: 10 | * The MegunoLink arduino library https://www.megunolink.com/documentation/arduino-integration/ 11 | 12 | MegunoLink Interface 13 | You can download a pre-made interface from here: 14 | https://github.com/Megunolink/MLP/raw/master/examples/InterfacePanel/RadioButtons/RadioButtons.mlpz 15 | 16 | You can find out more about MegunoLink and download a free trial from here 17 | https://www.megunolink.com/ 18 | https://www.megunolink.com/download/ 19 | ************************************************************************************************/ 20 | 21 | #include "MegunoLink.h" 22 | #include "CommandHandler.h" 23 | 24 | 25 | bool RBLow = true; 26 | bool RBMed = false; 27 | bool RBHigh = false; 28 | 29 | CommandHandler<> SerialCommandHandler; 30 | 31 | 32 | void Cmd_RadioButtonLow(CommandParameter &Parameters) 33 | { 34 | RBLow = Parameters.NextParameterAsInteger(); 35 | } 36 | 37 | void Cmd_RadioButtonMedium(CommandParameter &Parameters) 38 | { 39 | RBMed = Parameters.NextParameterAsInteger(); 40 | } 41 | 42 | void Cmd_RadioButtonHigh(CommandParameter &Parameters) 43 | { 44 | RBHigh = Parameters.NextParameterAsInteger(); 45 | } 46 | 47 | void Cmd_Print(CommandParameter &Parameters) 48 | { 49 | Serial.println("\n\n"); 50 | Serial.print("RB Low = "); Serial.println(RBLow); 51 | Serial.print("RB Med = "); Serial.println(RBMed); 52 | Serial.print("RB High = "); Serial.println(RBHigh); 53 | } 54 | 55 | void setup() 56 | { 57 | Serial.begin(9600); 58 | Serial.println("MegunoLink Pro Radio Button Demo"); 59 | Serial.println("-----------------------------"); 60 | 61 | SerialCommandHandler.AddCommand(F("RBLow"), Cmd_RadioButtonLow); 62 | SerialCommandHandler.AddCommand(F("RBMed"), Cmd_RadioButtonMedium); 63 | SerialCommandHandler.AddCommand(F("RBHigh"), Cmd_RadioButtonHigh); 64 | SerialCommandHandler.AddCommand(F("Print"), Cmd_Print); 65 | 66 | } 67 | 68 | void loop() 69 | { 70 | SerialCommandHandler.Process(); 71 | } -------------------------------------------------------------------------------- /src/DataStore.cpp: -------------------------------------------------------------------------------- 1 | #include "DataStore.h" 2 | #include "utility/CRC.h" 3 | 4 | uint8_t DataStore::s_uNextId = 0; 5 | 6 | void DataStore::Send(uint32_t uSenderId, byte DataContext, byte DataChannel, void const * pData, uint8_t uDataSize) 7 | { 8 | CMessageHeader Header; 9 | 10 | Header.Type = CMessageHeader::TYPE_Command; 11 | Header.Id = s_uNextId++; 12 | Header.SenderAddress = uSenderId; 13 | Header.TimeStamp = millis() & 0xffff; 14 | Header.Context = CMessageHeader::CTX_DataTransport; 15 | Header.Command = DataContext; 16 | Header.Command = (Header.Command << 8) | (DataChannel + 0x30); 17 | Header.Checksum = CalculateChecksum(Header, (uint8_t const *)pData, uDataSize); 18 | 19 | Serial.print((char)Header.Type); 20 | WriteHex(Header.Id); 21 | Serial.print('a'); 22 | WriteHex((uint8_t *)&Header.SenderAddress, sizeof(Header.SenderAddress)); 23 | Serial.print('t'); 24 | WriteHex((uint8_t *)&Header.TimeStamp, sizeof(Header.TimeStamp)); 25 | Serial.print('#'); 26 | WriteHex((uint8_t *)&Header.Checksum, sizeof(Header.Checksum)); 27 | Serial.print('-'); 28 | Serial.print((char)(Header.Context)); 29 | Serial.print((char)(Header.Command&0xff)); 30 | Serial.print((char)(Header.Command>>8)); 31 | Serial.print('('); 32 | Serial.print(uDataSize); 33 | Serial.print(')'); 34 | WriteHex(pData, uDataSize); 35 | 36 | Serial.println(); 37 | } 38 | 39 | uint16_t DataStore::CalculateChecksum(CMessageHeader const &rHeader, uint8_t const * pData, uint8_t uDataSize) 40 | { 41 | uint16_t uChecksum = ::CalculateChecksum((uint8_t const *) &rHeader + sizeof(uint16_t), sizeof(rHeader) - sizeof(uint16_t), (uint16_t)CMessageHeader::ChecksumSeed); 42 | uChecksum = ::CalculateChecksum(pData, uDataSize, uChecksum); 43 | 44 | return uChecksum; 45 | } 46 | 47 | void DataStore::WriteHex(uint8_t uData) 48 | { 49 | unsigned uNibble; 50 | char chOut; 51 | 52 | 53 | // High nibble. 54 | uNibble = (uData>>4)&0x0f; 55 | chOut = uNibble + ((uNibble < 10) ? '0' : ('A' - 10)); 56 | Serial.write(chOut); 57 | 58 | // Low nibble. 59 | uNibble = uData&0x0f; 60 | chOut = uNibble + ((uNibble < 10) ? '0' : ('A' - 10)); 61 | Serial.write(chOut); 62 | } 63 | 64 | void DataStore::WriteHex(const void *pSource, uint8_t uLength) 65 | { 66 | const uint8_t *pData = (uint8_t*) pSource; 67 | 68 | while (uLength--) 69 | WriteHex(*pData++); 70 | } 71 | 72 | -------------------------------------------------------------------------------- /src/EEPROMStore.h: -------------------------------------------------------------------------------- 1 | // Only supported for AVR micros because we use the special EEMEM directive 2 | // to automatically allocated memory in the eeprom. 3 | #if defined(__AVR__) 4 | 5 | #include 6 | #include 7 | 8 | template class EEPROMStore 9 | { 10 | // The data stored in the eprom. The EEMEM complier attribute instructs 11 | // the complier to locate this variable in the eeprom. 12 | struct EEMEM CEEPROMData 13 | { 14 | uint16_t m_uChecksum; 15 | TData m_UserData; 16 | 17 | } m_EEPROMData; 18 | 19 | public: 20 | TData Data; 21 | 22 | EEPROMStore() 23 | { 24 | Reset(); 25 | if (!Load()) 26 | Reset(); 27 | } 28 | 29 | bool Load() 30 | { 31 | CEEPROMData WorkingCopy; 32 | if (Load(WorkingCopy)) 33 | { 34 | memcpy(&Data, &WorkingCopy.m_UserData, sizeof(TData)); 35 | return true; 36 | } 37 | 38 | return false; 39 | } 40 | 41 | bool Save() 42 | { 43 | // We only save if the current version in the eeprom doesn't match the data we plan to save. 44 | // This helps protect the eeprom against save called many times within the arduino loop, 45 | // though it makes things a little slower. 46 | uint16_t uChecksum = CalculateChecksum(Data); 47 | CEEPROMData StoredVersion; 48 | if (!Load(StoredVersion) || StoredVersion.m_uChecksum != uChecksum || memcmp(&StoredVersion.m_UserData, &Data, sizeof(Data)) != 0) 49 | { 50 | eeprom_write_word(&m_EEPROMData.m_uChecksum, uChecksum); 51 | eeprom_write_block(&Data, &m_EEPROMData.m_UserData, sizeof(Data)); 52 | return true; 53 | } 54 | return false; 55 | } 56 | 57 | void Reset() 58 | { 59 | Data.Reset(); 60 | } 61 | 62 | private: 63 | bool Load(CEEPROMData &Result) 64 | { 65 | eeprom_read_block(&Result, (const void *)&m_EEPROMData, sizeof(CEEPROMData)); 66 | uint16_t uChecksum = CalculateChecksum(Result.m_UserData); 67 | return uChecksum == Result.m_uChecksum; 68 | } 69 | 70 | uint16_t CalculateChecksum(const TData &TestData) const 71 | { 72 | uint16_t uChecksum = 0; 73 | const uint8_t *pRawData = reinterpret_cast(&TestData); 74 | size_t szData = sizeof(TestData); 75 | 76 | while (szData--) 77 | { 78 | uChecksum = _crc16_update(uChecksum, *pRawData++); 79 | } 80 | 81 | return uChecksum; 82 | } 83 | }; 84 | #else 85 | #error EEPROMStore is only supported on AVR micros. 86 | #endif 87 | -------------------------------------------------------------------------------- /examples/Table/SendToTable/SendToTable.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program to send data to a MegunoLink property table and 3 | * receive property values back that update variables in the sketch. 4 | * 5 | * More Information 6 | * - http://www.megunolink.com/documentation/property-table/ 7 | * - https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 8 | * - https://www.megunolink.com/documentation/getting-started/processing-serial-commands/ 9 | * ********************************************************************************************** */ 10 | 11 | #include "MegunoLink.h" // for communicating with MegunoLink. 12 | #include "ArduinoTimer.h" // a timer to send data. 13 | #include "CommandHandler.h" // for handling serial commands. 14 | 15 | // Timer to keep track of sending data to MegunoLink. 16 | ::ArduinoTimer SendTimer; 17 | 18 | // Interval between sending updates to MegunoLink 19 | long UpdateInterval = 1000; // milliseconds. 20 | 21 | // Values we keep track of 22 | int Fish = 0; 23 | int Turtles = 0; 24 | 25 | // The table we are sending data to 26 | Table MyTable; 27 | 28 | // Command handlers to receive properties from MegunoLink 29 | CommandHandler<> SerialCommands; 30 | 31 | void setup() 32 | { 33 | Serial.begin(9600); 34 | Serial.println(F("Send data to MegunoLink table")); 35 | 36 | // Link variables to names we'll receive from MegunoLink 37 | // when the user sends properties from the table. See 38 | // https://www.megunolink.com/documentation/getting-started/processing-serial-commands/ 39 | SerialCommands.AddVariable(F("Fish"), Fish); 40 | SerialCommands.AddVariable(F("Turtles"), Turtles); 41 | SerialCommands.AddVariable(F("UpdateInterval"), UpdateInterval); 42 | 43 | // Set descriptions for the properties that we'll send 44 | // the the MegunoLink table. 45 | MyTable.SetDescription("Fish", "Lives in the sea"); 46 | MyTable.SetDescription("Turtles", "Very slow"); 47 | } 48 | 49 | void loop() 50 | { 51 | // Receive and process serial commands. 52 | SerialCommands.Process(); 53 | 54 | // Periodically send information to MegunoLink. See 55 | // https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 56 | if (SendTimer.TimePassed_Milliseconds(UpdateInterval)) 57 | { 58 | MyTable.SendData("Fish", Fish); 59 | MyTable.SendData("Turtles", Turtles); 60 | Fish += 3; 61 | Turtles += 1; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /examples/TimePlot/ESP8266TCPClientPlotting/ESP8266TCPClientPlotting.ino: -------------------------------------------------------------------------------- 1 | /* ****************************************************************** 2 | * This sketch sends analog measurements to a MegunoLink TCP Server 3 | * Set the Host to the IP address of your computer and Port to the 4 | * port you setup on MegunoLink's TCP Server configuration panel. 5 | * See https://www.megunolink.com/connecting/tcp-server for more information. 6 | */ 7 | 8 | #include 9 | #include "MegunoLink.h" 10 | 11 | #define USEWIFICONFIGFILE 12 | #ifdef USEWIFICONFIGFILE 13 | // Include SSID and password from a library file. For more information see: 14 | // https://www.megunolink.com/articles/wireless/how-do-i-connect-to-a-wireless-network-with-the-esp32/ 15 | #include "WiFiConfig.h" 16 | #else 17 | // Option 2 18 | const char *SSID = "Your SSID"; 19 | const char *WiFiPassword = "Your Password"; 20 | #endif 21 | 22 | const char *Host = "192.168.15.117"; 23 | const unsigned Port = 11000; 24 | 25 | // We'll use a single client and remain connected. The Arduino doesn't 26 | // inform the server that the client has disconnected which leaves a 27 | // lot of dangling connections to manage if we use a new client 28 | // for each message. 29 | WiFiClient Client; 30 | 31 | void ConnectToWiFi() 32 | { 33 | 34 | WiFi.mode(WIFI_STA); 35 | WiFi.begin(SSID, WiFiPassword); 36 | Serial.print("Connecting to "); Serial.println(SSID); 37 | 38 | uint8_t i = 0; 39 | while (WiFi.status() != WL_CONNECTED) 40 | { 41 | Serial.print('.'); 42 | delay(500); 43 | 44 | if ((++i % 16) == 0) 45 | { 46 | Serial.println(F(" still trying to connect")); 47 | } 48 | } 49 | 50 | Serial.print(F("Connected. My IP address is: ")); 51 | Serial.println(WiFi.localIP()); 52 | } 53 | 54 | WiFiClient *GetClient() 55 | { 56 | if (!Client.connected() && Client.connect(Host, Port)) 57 | { 58 | return &Client; 59 | } 60 | 61 | return Client.connected() ? &Client : NULL; 62 | } 63 | 64 | void SendMeasurement(unsigned Value) 65 | { 66 | WiFiClient *pClient = GetClient(); 67 | 68 | if (pClient != NULL) 69 | { 70 | TimePlot Plot("", *pClient); 71 | Plot.SendData("ADC Value", Value); 72 | } 73 | else 74 | { 75 | Serial.println("TCP Connection failed"); 76 | } 77 | } 78 | 79 | void setup() 80 | { 81 | Serial.begin(9600); 82 | 83 | ConnectToWiFi(); 84 | } 85 | 86 | void loop() 87 | { 88 | unsigned Measurement = analogRead(0); 89 | SendMeasurement(Measurement); 90 | 91 | delay(1000); 92 | } 93 | -------------------------------------------------------------------------------- /examples/CommandHandler/MultiSourceCommandHandler/MultiSourceCommandHandler.ino: -------------------------------------------------------------------------------- 1 | /* ************************************************************************ 2 | MultiSourceCommandHandler 3 | 4 | This example demonstrates decoding serial commands received from two 5 | serial sources and dispatching commands. Each serial source uses a separate 6 | command processor to buffer characters and decode commands. A single 7 | command dispatcher is used so serial commands can be received from either 8 | serial source. 9 | 10 | The example processes the following commands: 11 | * !SetTurtleCount \r\n 12 | Set's the global NumberOfTurtles to , an integer. 13 | * !GetTurtleCount\r\n 14 | Writes the NumberOfTurtles global value to the serial stream that 15 | sent the command. 16 | 17 | More Information 18 | * https://www.megunolink.com/documentation/build-arduino-interface/ 19 | * https://www.megunolink.com/documentation/interface-panel/ 20 | * https://www.megunolink.com/documentation/arduino-libraries/serial-command-handler/ 21 | 22 | You can find out more about MegunoLink and download a free trial from: 23 | * https://www.megunolink.com/ 24 | * https://www.megunolink.com/download/ 25 | 26 | This example requires the MegunoLink library for Arduino: 27 | * Setup: https://www.megunolink.com/documentation/install/arduino-integration-setup/ 28 | * Reference https://www.megunolink.com/documentation/arduino-library/ 29 | ************************************************************************ */ 30 | 31 | #include "MegunoLink.h" 32 | #include "CommandProcessor.h" 33 | 34 | int NumberOfTurtles = 0; 35 | 36 | CommandDispatcher<> CommonCommands; 37 | CommandProcessor<> SerialCommandHandler(CommonCommands, Serial); 38 | CommandProcessor<> Serial2CommandHandler(CommonCommands, Serial2); 39 | 40 | void Cmd_GetTurtleCount(CommandParameter &Parameters) 41 | { 42 | Parameters.Response.print(F("Number of turtles = ")); 43 | Parameters.Response.println(NumberOfTurtles); 44 | } 45 | 46 | void Cmd_SetTurtleCount(CommandParameter &Parameters) 47 | { 48 | NumberOfTurtles=Parameters.NextParameterAsInteger(); 49 | } 50 | 51 | void setup() 52 | { 53 | Serial.begin(9600); 54 | Serial.println("MegunoLink Pro Turtle Monitor"); 55 | Serial.println("-----------------------------"); 56 | 57 | Serial2.begin(4800); 58 | 59 | CommonCommands.AddCommand(F("SetTurtleCount"), Cmd_SetTurtleCount); 60 | CommonCommands.AddCommand(F("GetTurtleCount"), Cmd_GetTurtleCount); 61 | 62 | } 63 | 64 | void loop() 65 | { 66 | SerialCommandHandler.Process(); 67 | Serial2CommandHandler.Process(); 68 | } 69 | -------------------------------------------------------------------------------- /src/utility/StreamParser.cpp: -------------------------------------------------------------------------------- 1 | #include "StreamParser.h" 2 | 3 | using namespace MLP; 4 | 5 | StreamParser::StreamParser( MLP::CommandDispatcherBase &rCommandHandler, 6 | char *pchReceiveBuffer, 7 | unsigned uBufferSize, 8 | Stream &rSourceStream /*= Serial*/, 9 | char chStartOfMessage /*= '!'*/, 10 | char chEndOfMessage /*= '\r'*/ ) 11 | : m_pCommandHandler(&rCommandHandler) 12 | , m_pSource(&rSourceStream) 13 | , m_chStartOfMessage(chStartOfMessage) 14 | , m_chEndOfMessage(chEndOfMessage) 15 | , m_pchBuffer(pchReceiveBuffer) 16 | , m_uMaxBufferSize(uBufferSize) 17 | { 18 | Reset(); 19 | } 20 | 21 | StreamParser::StreamParser(char *pchReceiveBuffer, unsigned uBufferSize) 22 | : m_pchBuffer(pchReceiveBuffer) 23 | , m_uMaxBufferSize(uBufferSize) 24 | { 25 | Reset(); 26 | } 27 | 28 | 29 | void StreamParser::Process() 30 | { 31 | while (m_pSource != NULL && m_pSource->available() > 0) 32 | { 33 | char chNext = m_pSource->read(); 34 | 35 | if (chNext == m_chStartOfMessage) 36 | { 37 | Reset(); 38 | m_pchBuffer[0] = chNext; // the start character serves as a flag that this message is valid. 39 | ++m_uNextCharacter; 40 | } 41 | else if (chNext == m_chEndOfMessage) 42 | { 43 | if (m_uNextCharacter > 0 && m_pchBuffer[0] == m_chStartOfMessage) 44 | { 45 | if (!m_bOverflow) 46 | { 47 | // We have a valid message. Dispatch it. 48 | m_pchBuffer[m_uNextCharacter] = '\0'; 49 | DispatchMessage(); 50 | } 51 | else 52 | { 53 | Serial.println(F("Ovrflw")); 54 | } 55 | Reset(); 56 | } 57 | } 58 | else 59 | { 60 | // Store the character and advance the buffer. If there isn't enough 61 | // room for the message to be terminated by a null, flag overflow. 62 | if (!m_bOverflow) 63 | { 64 | m_pchBuffer[m_uNextCharacter++] = chNext; 65 | m_bOverflow = m_uNextCharacter >= (m_uMaxBufferSize - 1); 66 | } 67 | } 68 | } 69 | } 70 | 71 | void StreamParser::DispatchMessage() 72 | { 73 | m_pCommandHandler->DispatchCommand(m_pchBuffer + 1, *m_pSource); // First character is start of message signal. 74 | } 75 | 76 | void StreamParser::Reset() 77 | { 78 | m_uNextCharacter = 0; 79 | m_bOverflow = false; 80 | } -------------------------------------------------------------------------------- /examples/ExponentialFilterExplorer/ExponentialFilterExplorer.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | In this example we demonstrate our Filter library. MegunoLink's Interface Panel is used to allow 4 | adjustment of the filter time constant. This allows you to tune the amount of smoothing applied. 5 | 6 | More Information 7 | * http://www.MegunoLink.com/documentation/arduino-libraries/exponential-filter/ 8 | * http://www.megunolink.com/documentation/plotting/ 9 | 10 | This Example Requires: 11 | * The MegunoLink arduino library https://www.megunolink.com/documentation/arduino-integration/ 12 | 13 | MegunoLink Interface 14 | You can download a pre-made interface from here: 15 | https://github.com/Megunolink/MLP/raw/master/examples/ExponentialFilterExplorer/ExponentialFilterExplorer.mlpz 16 | 17 | You can find out more about MegunoLink and download a free trial from here 18 | https://www.megunolink.com/ 19 | https://www.megunolink.com/download/ 20 | ************************************************************************************************/ 21 | 22 | #include "MegunoLink.h" 23 | #include "Filter.h" 24 | #include "CommandHandler.h" 25 | 26 | // Create a new exponential filter with a weight of 10 and initial value of 0. 27 | ExponentialFilter ADCFilter(10, 0); 28 | 29 | CommandHandler<> SerialCommands; 30 | 31 | void Cmd_SetFilter(CommandParameter &p) 32 | { 33 | int NewFilterWeight = p.NextParameterAsInteger(ADCFilter.GetWeight()); 34 | if (NewFilterWeight < 0) 35 | { 36 | NewFilterWeight = 0; 37 | } 38 | if (NewFilterWeight > 100) 39 | { 40 | NewFilterWeight = 100; 41 | } 42 | 43 | ADCFilter.SetWeight(NewFilterWeight); 44 | Serial.print(F("Filter weight set to: ")); 45 | Serial.println(NewFilterWeight); 46 | } 47 | 48 | void setup() 49 | { 50 | Serial.begin(9600); 51 | Serial.println("Exponential Filter Explorer"); 52 | Serial.println("---------------------------"); 53 | Serial.println(); 54 | Serial.println("Commands: "); 55 | Serial.println(" !SetFilter value\\r\\n"); 56 | Serial.println("Commands: "); 57 | Serial.println(" !SetFilter 20\\r\\n set filter parameter to 20%. Range is 0..100"); 58 | 59 | SerialCommands.AddCommand(F("SetFilter"), Cmd_SetFilter); 60 | } 61 | 62 | void loop() 63 | { 64 | SerialCommands.Process(); 65 | 66 | int RawValue = analogRead(0); 67 | ADCFilter.Filter(RawValue); 68 | 69 | TimePlot Plot; 70 | Plot.SendData("Raw", RawValue); 71 | Plot.SendData("Filtered", ADCFilter.Current()); 72 | 73 | delay(100); 74 | } 75 | -------------------------------------------------------------------------------- /examples/CircularBuffer/CircularBuffer.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | This example demonstrates our Circular Buffer library. Button push timestamps are recorded in a 4 | circular buffer and periodically written out the serial port. 5 | 6 | More Information 7 | * https://www.megunolink.com/documentation/arduino-libraries/circular-buffer/ 8 | * https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 9 | 10 | This Example Requires: 11 | * The MegunoLink arduino library https://www.megunolink.com/documentation/arduino-integration/ 12 | 13 | You can find out more about MegunoLink and download a free trial from: 14 | * https://www.megunolink.com/ 15 | * https://www.megunolink.com/download/ 16 | 17 | ************************************************************************************************/ 18 | 19 | #include "CircularBuffer.h" 20 | #include "ArduinoTimer.h" 21 | 22 | // The buffer which will hold button presses. We use the time stamp from 23 | // the micros timer to store the time a button press was registered. So 24 | // the buffer must store unsigned long values. Up to 20 button times 25 | // will be stored before old ones are overwritten. 26 | typedef CircularBuffer ButtonTimeBuffer; 27 | ButtonTimeBuffer ButtonTimes; 28 | 29 | // The pin that the button is connected to. The other side of the button 30 | // should be connected to ground. 31 | const int ButtonPin = 3; 32 | 33 | // The amount of time between writing out all the data in the circular buffer 34 | // and a timer to keep track if that amount of time has passed yet. 35 | const int PrintingPeriod = 10; // seconds 36 | ::ArduinoTimer PrintingTimer; 37 | 38 | void setup() 39 | { 40 | Serial.begin(9600); 41 | 42 | pinMode(ButtonPin, INPUT_PULLUP); 43 | } 44 | 45 | void loop() 46 | { 47 | bool ButtonPressed = digitalRead(ButtonPin) == 0; 48 | static bool WasPressed = false; 49 | 50 | if (ButtonPressed) 51 | { 52 | if (!WasPressed) 53 | { 54 | WasPressed = true; 55 | unsigned long CurrentTime = micros(); 56 | ButtonTimes.Add(CurrentTime); 57 | } 58 | } 59 | else 60 | { 61 | WasPressed = false; 62 | } 63 | 64 | if (PrintingTimer.TimePassed_Seconds(PrintingPeriod)) 65 | { 66 | for(ButtonTimeBuffer::ForwardIterator Iterator(ButtonTimes); Iterator.AtEnd() == false; Iterator.Next()) 67 | { 68 | Serial.print(Iterator.ItemNumber()); 69 | Serial.print('\t'); 70 | Serial.println(Iterator.CurrentValue()); 71 | } 72 | 73 | ButtonTimes.Clear(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MegunoLink library for Arduino 2 | ============================== 3 | 4 | ![example build test](https://github.com/github/docs/actions/workflows/githubci.yml/badge.svg?event=push) 5 | 6 | An [Arduino library](http://www.megunolink.com/documentation/arduino-libraries/) for sending data and commands to [MegunoLink](https://www.MegunoLink.com) visualizers including: 7 | 8 | * [Interface panel](https://www.megunolink.com/documentation/interface-panel/) 9 | * [XY-Plots](https://www.megunolink.com/documentation/plotting/xy-plot/) 10 | * [Time plots](https://www.megunolink.com/documentation/plotting/time-plot/) 11 | * [Property tables](https://www.megunolink.com/documentation/table/property-table/) 12 | * [Record tables](https://www.megunolink.com/documentation/table/record-table/) 13 | * [Message stream](https://www.megunolink.com/documentation/serial-monitors/message-monitor-visualizer/) 14 | * [Message monkey](https://www.megunolink.com/documentation/message-monkey/) 15 | * [Maps](https://www.megunolink.com/documentation/mapping/) 16 | * [Test reports](https://www.megunolink.com/documentation/program-device/test-monitor-panel/) 17 | * [Scheduled reporting](https://www.megunolink.com/documentation/reporting/scheduled-reporting/) 18 | * [Playing audio clips and speech](https://www.megunolink.com/documentation/play-sounds/) 19 | 20 | The library also supports: 21 | 22 | * A [command handler for serial commands](http://www.megunolink.com/documentation/arduino-libraries/serial-command-handler/) 23 | * A class to make it easier to write [timer driven code](http://www.megunolink.com/documentation/arduino-libraries/arduino-timer/) with Arduino millis() timer 24 | * A template for [storing data in the eeprom](https://www.megunolink.com/documentation/arduino-libraries/eepromstore/) 25 | * An [exponential filter](https://www.megunolink.com/documentation/arduino-libraries/exponential-filter/) 26 | * A [circular buffer template](https://www.megunolink.com/documentation/arduino-libraries/circular-buffer/) 27 | * A command processor for dispatching commands 28 | 29 | Visit [www.MegunoLink.com](https://www.MegunoLink.com) to [download MegunoLink](http://www.MegunoLink.com/download) and learn more. 30 | 31 | Arduino Installation 32 | -------------------- 33 | Install the library into the `libraries` folder of your Arduino installation or use [MegunoLink's Arduino integration setup](https://www.megunolink.com/documentation/install/arduino-integration-setup/) tool. 34 | 35 | 36 | Library dependecies: none. 37 | 38 | License Information 39 | -------------------------- 40 | The hardware is released under the GNU Lesser General Public License (LGPL) 41 | 42 | Distributed as-is; no warranty is given. 43 | -------------------------------------------------------------------------------- /examples/TimePlot/Sinewave/Sinewave.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | In this example we use MegunoLink's Time Plot visualizer to plot Sinewave data in real time. 4 | 5 | More Information 6 | * https://www.megunolink.com/documentation/getting-started/plotting-data/ 7 | 8 | This Example Requires: 9 | * The MegunoLink arduino library https://www.megunolink.com/documentation/getting-started/arduino-integration/ 10 | 11 | MegunoLink Interface 12 | You can download a pre-made interface from here: 13 | https://github.com/Megunolink/MLP/raw/master/examples/TimePlot/Sinewave/Sinewave.mlpz 14 | 15 | You can find out more about MegunoLink and download a free trial from here 16 | https://www.megunolink.com/ 17 | https://www.megunolink.com/download/ 18 | ************************************************************************************************/ 19 | 20 | #include "MegunoLink.h" 21 | 22 | // Uncomment if you would like to use plotting channels 23 | // (see https://www.megunolink.com/documentation/message-channels/) 24 | // TimePlot MyPlot("Waveforms"); //"Waveforms" = the taget plotting channel (remember to select this in megunolink) 25 | 26 | TimePlot MyPlot; //no channel selected 27 | 28 | void setup() 29 | { 30 | Serial.begin(9600); 31 | 32 | MyPlot.SetTitle("Sine and Cosine Function Waveforms"); 33 | MyPlot.SetXLabel("Time"); 34 | MyPlot.SetYLabel("Amplitude"); 35 | 36 | // Set the plotting parameters. "Sinewave" = series name, Plot::Blue = line colour 37 | // 2 = line width, Plot::Square = marker style 38 | MyPlot.SetSeriesProperties("Sinewave", Plot::Blue, Plot::Solid, 2, Plot::Square); 39 | MyPlot.SetSeriesProperties("Cosinewave", Plot::Red, Plot::Solid, 2, Plot::Square); 40 | 41 | // Colours include 42 | // Red, Green, Blue, Yellow, Black, Magenta, Cyan, White 43 | 44 | // Markers include 45 | // Square, Diamond, Triangle, Circle, Cross, Plus, Star, DownwardTriangle, NoMarker 46 | 47 | // Line style 48 | // Solid, Dashed, Dotted, DashDot, DashDotDot 49 | 50 | } 51 | 52 | 53 | void loop() 54 | { 55 | double dY, dY2; 56 | float seconds; 57 | float frequency = 0.5; //Hz 58 | float phase = 3.141/2; 59 | 60 | seconds = (float)millis()/1000; 61 | 62 | dY = sin(2 * 3.141 * frequency * seconds); 63 | dY2 = cos(2 * 3.141 * frequency * seconds + phase); 64 | 65 | //Send Data To MegunoLink Pro 66 | MyPlot.SendData(F("Sinewave"),dY); // Sinewave = series name, dY = data to plot 67 | MyPlot.SendData(F("Cosinewave"),dY2); // By wrapping strings in F("") we can save ram by storing strings in program memory 68 | 69 | 70 | delay(10); 71 | } 72 | -------------------------------------------------------------------------------- /examples/Getting Started/XYPlotButtonBounce/XYPlotButtonBounce.ino: -------------------------------------------------------------------------------- 1 | /* ********************************************************************************************** 2 | * Example program to record button bounce and plot the waveform on MegunoLink's XY visualiser. 3 | * Find the MegunoLink project (XY plot button bounce.mlpz), that goes with this example, in the same folder 4 | * as this Arduino code file. 5 | * 6 | * For more information: 7 | * Getting started with plotting (uses time-plot, which is similar to xy-plot): 8 | * https://www.megunolink.com/documentation/getting-started/plotting-data/ 9 | * XY plot visualizer reference: 10 | * https://www.megunolink.com/documentation/plotting/xy-plot/ 11 | * Installing the MegunoLink Arduino library: 12 | * https://www.megunolink.com/documentation/getting-started/arduino-integration/ 13 | * Sending data to multiple plots: 14 | * https://www.megunolink.com/documentation/plotting/sending-data-to-multiple-plots/ 15 | * ********************************************************************************************** */ 16 | 17 | #include "MegunoLink.h" 18 | 19 | const int InputPin = 7; // Pin that switch is connected to 20 | 21 | void setup() 22 | { 23 | Serial.begin(57600); 24 | Serial.println(F("Button Bounce Tester")); 25 | 26 | pinMode(InputPin, INPUT_PULLUP); 27 | } 28 | 29 | void loop() 30 | { 31 | // Trigger data capture when the switch is closed 32 | int ButtonState = digitalRead(InputPin); 33 | if (ButtonState == 0) 34 | { 35 | // To accurately capture the bounce, measurements are stored in this RAM 36 | // buffer then sent to the plot. This approach avoids delays caused by 37 | // sending serial data. 38 | const int NumberOfMeasurements = 200; 39 | long MeasurementTime[NumberOfMeasurements]; // microseconds 40 | int Measurement[NumberOfMeasurements]; 41 | 42 | // Capture bounce 43 | MeasurementTime[0] = micros(); 44 | Measurement[0] = ButtonState; 45 | for(int i = 1; i Cmds; 25 | ::ArduinoTimer ExperimentTimer; 26 | 27 | 28 | int FileNumber = 1; 29 | int MeasurementsSaved = 1; 30 | const int MeasurementsPerFile = 10; 31 | const int NumberOfRuns = 5; 32 | 33 | bool ExperimentRunning; 34 | 35 | void StartNewLogFile(int LogFileNumber) 36 | { 37 | String FileName("Log"); 38 | FileName += LogFileNumber; 39 | FileName += ".txt"; 40 | Msg.LogTo(FileName); 41 | MeasurementsSaved = 0; 42 | } 43 | 44 | void StoreMeasurement() 45 | { 46 | auto Value = analogRead(0); 47 | Msg.Send(millis(), Value); 48 | ++MeasurementsSaved; 49 | } 50 | 51 | void Cmd_StartExperiment(CommandParameter &p) 52 | { 53 | ExperimentRunning = true; 54 | FileNumber = 0; 55 | StartNewLogFile(++FileNumber); 56 | } 57 | 58 | void Cmd_StopExperiment(CommandParameter &p) 59 | { 60 | Msg.StopLogging(); 61 | ExperimentRunning = false; 62 | } 63 | 64 | void setup() 65 | { 66 | Serial.begin(9600); 67 | Cmds.AddCommand(F("Start"), Cmd_StartExperiment); 68 | Cmds.AddCommand(F("Stop"), Cmd_StopExperiment); 69 | } 70 | 71 | void loop() 72 | { 73 | Cmds.Process(); 74 | 75 | if (ExperimentRunning) 76 | { 77 | if (ExperimentTimer.TimePassed_Milliseconds(250)) 78 | { 79 | StoreMeasurement(); 80 | } 81 | 82 | if (MeasurementsSaved == MeasurementsPerFile) 83 | { 84 | ++FileNumber; 85 | if (FileNumber <= NumberOfRuns) 86 | { 87 | // Start a new experiment run. 88 | StartNewLogFile(FileNumber); 89 | } 90 | else 91 | { 92 | // Stop the experiment when all runs have been completed 93 | ExperimentRunning = false; 94 | Msg.StopLogging(); 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /examples/TimePlot/EthernetUDPPlotting/EthernetUDPPlotting.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | Data is sent from a Wiznet 5100 ethernet adapter over UDP to MegunoLink's Time Plot visualiser 4 | where it is plotted in realtime. 5 | 6 | This example uses the raw plotting protocol. Detail about this procotol can be found here: 7 | https://www.megunolink.com/documentation/plotting/plotting-message-reference/ 8 | 9 | More Information 10 | * http://www.megunolink.com/documentation/plotting/ 11 | 12 | This Example Requires: 13 | * The MegunoLink library for Arduino 14 | https://www.megunolink.com/documentation/arduino-integration/ 15 | * The Ethernet library 16 | https://www.arduino.cc/reference/en/libraries/ethernet/ 17 | https://github.com/arduino-libraries/Ethernet 18 | 19 | MegunoLink Interface 20 | You can download a pre-made interface from: 21 | * https://github.com/Megunolink/MLP/raw/master/examples/TimePlot/EthernetUDPlotting/EthernetUDPPlotting.mlpz 22 | 23 | You can find out more about MegunoLink and download a free trial from: 24 | * https://www.megunolink.com/ 25 | * https://www.megunolink.com/download/ 26 | ************************************************************************************************/ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | // Enter a MAC address 33 | byte mac[] = { 34 | 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 35 | 36 | //Local port to listen to (set this in megunolink) 37 | unsigned int localPort = 1269; 38 | 39 | //Local IP address of the computer you want to send data to (255.255.255.255 = broadcast address) 40 | const char localIPAddress[] = "255.255.255.255"; 41 | 42 | // An EthernetUDP instance to let us send and receive packets over UDP 43 | EthernetUDP Udp; 44 | 45 | // Timer Variables 46 | unsigned long LastPlotTime = 0; 47 | 48 | void setup() 49 | { 50 | Serial.begin(9600); 51 | Serial.println("Setup Started"); 52 | 53 | // start the Ethernet and UDP. An IP address will be found automatically. 54 | Ethernet.begin(mac); 55 | Udp.begin(localPort); 56 | 57 | Serial.println("Setup Complete"); 58 | } 59 | 60 | void loop() 61 | { 62 | int adcval = analogRead(0); //Read adc value 63 | 64 | 65 | //Plot Data Every 1000ms 66 | if((millis()-LastPlotTime)>1000) 67 | { 68 | LastPlotTime = millis(); 69 | 70 | //notify user using normal serial port 71 | Serial.println("sending udp data"); 72 | 73 | //Send UDP data 74 | Udp.beginPacket(localIPAddress, localPort); 75 | Udp.write("{TIMEPLOT|data|adc vale|T|"); 76 | Udp.print(adcval); 77 | Udp.write("}\n"); 78 | Udp.endPacket(); 79 | } 80 | } 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /examples/InterfacePanel/Prompt/Prompt.ino: -------------------------------------------------------------------------------- 1 | /* ************************************************************************ 2 | Prompting the user 3 | 4 | On receiving a serial message to "launch a missle", this program sends a 5 | command to MegunoLink requesting confirmation. In response, MegunoLink 6 | displays a message box and sends a serial message to either confirm or 7 | abort the "launch". A simple timeout also aborts the launch if confirmation 8 | isn't received in time. 9 | 10 | The example folder also contains a MegunoLink project, with an Interface 11 | Panel for this example. To download a free MegunoLink trial, visit: 12 | - http://www.MegunoLink.com to download MegunoLink. 13 | 14 | More Information 15 | - https://www.megunolink.com/documentation/getting-started/build-arduino-interface/ 16 | - https://www.megunolink.com/documentation/interface-panel/prompt/ 17 | - https://www.megunolink.com/documentation/getting-started/processing-serial-commands/ 18 | - https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 19 | 20 | This example requires: 21 | * Our MegunoLink Arduino library 22 | https://www.megunolink.com/documentation/arduino-library/ 23 | ************************************************************************ */ 24 | 25 | #include "MegunoLink.h" 26 | #include "CommandHandler.h" 27 | #include "ArduinoTimer.h" 28 | 29 | InterfacePanel Panel; 30 | CommandHandler<> SerialCmds; 31 | 32 | bool WaitingForPromptResponse = false; 33 | int CurrentPromptId = 1; 34 | ::ArduinoTimer PromptTimeout; 35 | 36 | void Cmd_BeginMissileLaunch(CommandParameter& p) 37 | { 38 | if (WaitingForPromptResponse) 39 | { 40 | if (PromptTimeout.TimePassed_Seconds(5)) 41 | { 42 | WaitingForPromptResponse = false; 43 | } 44 | else 45 | { 46 | Serial.println(F("Missile launch underway. Waiting for confirmation")); 47 | } 48 | } 49 | 50 | if (!WaitingForPromptResponse) 51 | { 52 | WaitingForPromptResponse = true; 53 | Panel.ShowPrompt("MissilePrompt", ++CurrentPromptId, "Do you really want to launch the missile now?"); 54 | PromptTimeout.Reset(); 55 | } 56 | } 57 | 58 | void Cmd_HandlePromptResponse(CommandParameter& p) 59 | { 60 | int PromptId = p.NextParameterAsInteger(); 61 | const char* Response = p.NextParameter(); 62 | if (PromptId == CurrentPromptId) 63 | { 64 | WaitingForPromptResponse = false; 65 | bool Launch = *Response != '\0' && *Response == 'Y'; 66 | if (Launch) 67 | { 68 | Serial.println(F("Fire missiles!!")); 69 | } 70 | else 71 | { 72 | Serial.println(F("Launch aborted.")); 73 | } 74 | } 75 | } 76 | 77 | void setup() 78 | { 79 | Serial.begin(9600); 80 | Serial.println(F("Missile launch program")); 81 | 82 | SerialCmds.AddCommand(F("BeginLaunch"), Cmd_BeginMissileLaunch); 83 | SerialCmds.AddCommand(F("PromptResponse"), Cmd_HandlePromptResponse); 84 | } 85 | 86 | void loop() 87 | { 88 | SerialCmds.Process(); 89 | } 90 | -------------------------------------------------------------------------------- /examples/InterfacePanel/IsMegunoLinkConnected/IsMegunoLinkConnected.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | In this example we demonstrate how you can use MegunoLink's Interface Panel and our command handler 4 | library to identify when your device is connected to MegunoLink and when its not. This allows you 5 | to change the behaviour of your device dynamically. For example when its plugged in you might want 6 | to enter a configuration mode and when its unplugged it should run the program as usual. 7 | 8 | More Information 9 | * https://www.megunolink.com/documentation/build-arduino-interface/ 10 | * https://www.megunolink.com/documentation/interface-panel/ 11 | * https://www.megunolink.com/documentation/arduino-libraries/serial-command-handler/ 12 | * https://www.megunolink.com/documentation/getting-started/processing-serial-commands/ 13 | * https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 14 | 15 | This Example Requires: 16 | * The MegunoLink arduino library https://www.megunolink.com/documentation/arduino-integration/ 17 | 18 | MegunoLink Interface 19 | You can download a pre-made interface from here: 20 | https://github.com/Megunolink/MLP/raw/master/examples/InterfacePanel/IsMegunoLinkConnected/IsMegunoLinkConnected.mlpz 21 | 22 | You can find out more about MegunoLink and download a free trial from here 23 | https://www.megunolink.com/ 24 | https://www.megunolink.com/download/ 25 | ************************************************************************************************/ 26 | 27 | #include "MegunoLink.h" 28 | #include "ArduinoTimer.h" 29 | #include "CommandHandler.h" 30 | 31 | InterfacePanel MyPanel; 32 | ::ArduinoTimer MLPCheckTimer; 33 | ::ArduinoTimer StatusPrintTimer; 34 | CommandHandler<> MyCommandHanlder; 35 | 36 | uint32_t LastAnnounceTime = 0; 37 | uint32_t MLPNotThereTimeout = 10*1000; //mS 38 | bool IsMLPThere = false; 39 | 40 | // This function is called whenever MegunoLink successfully responds 41 | void Cmd_MegunoLinkIsHere(CommandParameter &Parameters) 42 | { 43 | LastAnnounceTime = millis(); 44 | } 45 | 46 | 47 | void setup() 48 | { 49 | Serial.begin(9600); 50 | MyCommandHanlder.AddCommand(F("MLIsHere"), Cmd_MegunoLinkIsHere); 51 | } 52 | 53 | 54 | void loop() 55 | { 56 | MyCommandHanlder.Process(); 57 | 58 | // Sends a message to MegunoLink every 5 seconds to check connection 59 | if (MLPCheckTimer.TimePassed_Seconds(5)) 60 | { 61 | MyPanel.CallCommand(F("Announce")); 62 | } 63 | 64 | // If the arduino has herd from MegunoLink in the last timeout period then it returns true, else false. 65 | IsMLPThere = ((millis() - LastAnnounceTime) > MLPNotThereTimeout) ? false : true; 66 | 67 | // This prints the result every 1 second to confirm its working 68 | if (StatusPrintTimer.TimePassed_Milliseconds(1000)) 69 | { 70 | Serial.print("Is MLP there? "); 71 | Serial.println(IsMLPThere); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /examples/InterfacePanel/SetParameters/SetParameters.ino: -------------------------------------------------------------------------------- 1 | /* *********************************************************************** 2 | * Example program to update an Arduino variable using serial commands 3 | * sent from an interface panel in MegunoLink. Find the MegunoLink project 4 | * (SetParameters.mlpz), that goes with this example, in the same folder 5 | * as this Arduino code file. 6 | * 7 | * For more information: 8 | * Getting started building Arduino interfaces 9 | * https://www.megunolink.com/documentation/getting-started/build-arduino-interface/ 10 | * Getting started processing serial commands 11 | * https://www.megunolink.com/documentation/getting-started/processing-serial-commands/ 12 | * Installing the MegunoLink Arduino library: 13 | * https://www.megunolink.com/documentation/getting-started/arduino-integration/ 14 | * Interface panel reference 15 | * https://www.megunolink.com/documentation/interface-panel/ 16 | * *********************************************************************** */ 17 | 18 | // Library to handle serial commands 19 | #include "CommandHandler.h" 20 | 21 | // Library to send commands/data to MegunoLink 22 | #include "MegunoLink.h" 23 | 24 | /// 25 | /// The Arduino variable to change using a serial command. 26 | /// 27 | int NumberOfTurtles = 0; 28 | 29 | /// 30 | /// Looks after parsing and dispatching serial commands to Arduino functions 31 | /// 32 | CommandHandler<> SerialCommandHandler; 33 | 34 | /// 35 | /// Called when a 'GetTurtleCount' command is received to query the 36 | /// current count. 37 | /// 38 | /// No parameters 39 | void Cmd_GetTurtleCount(CommandParameter &Parameters) 40 | { 41 | // Report count to serial stream. 42 | Serial.print(F("Number of turtles = ")); 43 | Serial.println(NumberOfTurtles); 44 | 45 | // Send count to interface panel. 46 | InterfacePanel TurtleInterface; 47 | TurtleInterface.SetNumber(F("numTurtles"), NumberOfTurtles); 48 | } 49 | 50 | /// 51 | /// Called when a 'SetTurtleCount' command is received to update the variable. 52 | /// 53 | /// Contains new count 54 | void Cmd_SetTurtleCount(CommandParameter &Parameters) 55 | { 56 | // Update Arduino variable with parameter value sent with command. 57 | NumberOfTurtles=Parameters.NextParameterAsInteger(); 58 | } 59 | 60 | void setup() 61 | { 62 | Serial.begin(9600); 63 | Serial.println("MegunoLink Pro Turtle Monitor"); 64 | Serial.println("-----------------------------"); 65 | 66 | // Register commands we can handle. 67 | SerialCommandHandler.AddCommand(F("SetTurtleCount"), Cmd_SetTurtleCount); 68 | SerialCommandHandler.AddCommand(F("GetTurtleCount"), Cmd_GetTurtleCount); 69 | 70 | } 71 | 72 | void loop() 73 | { 74 | // Dispatch and process commands as they are received from the serial port. 75 | SerialCommandHandler.Process(); 76 | } 77 | -------------------------------------------------------------------------------- /examples/TimePlot/RainbowSinewave/RainbowSinewave.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | In this example we use MegunoLink's Time Plot visualizer to plot Sinewave data in real time. The 4 | plot color is changed from red -> green -> blue. 5 | 6 | More Information 7 | * http://www.megunolink.com/documentation/plotting/ 8 | 9 | This Example Requires: 10 | * The MegunoLink arduino library https://www.megunolink.com/documentation/arduino-integration/ 11 | 12 | MegunoLink Interface 13 | You can download a pre-made interface from here: 14 | https://github.com/Megunolink/MLP/raw/master/examples/TimePlot/Sinewave/Sinewave.mlpz 15 | 16 | You can find out more about MegunoLink and download a free trial from here 17 | https://www.megunolink.com/ 18 | https://www.megunolink.com/download/ 19 | ************************************************************************************************/ 20 | 21 | #include "MegunoLink.h" 22 | 23 | // Uncomment if you would like to use plotting channels 24 | // TimePlot MyPlot("Waveforms"); //"Waveforms" = the taget plotting channel (remember to select this in megunolink) 25 | 26 | TimePlot MyPlot; //no channel selected 27 | 28 | uint32_t Colors[3] = {0, 0, 0}; 29 | int ColorIndex = 0; 30 | 31 | void setup() 32 | { 33 | Serial.begin(9600); 34 | 35 | MyPlot.SetTitle("Sine and Cosine Function Waveforms"); 36 | MyPlot.SetXLabel("Time"); 37 | MyPlot.SetYLabel("Amplitude"); 38 | 39 | // Set the plotting parameters. "Sinewave" = series name, Plot::Blue = line colour 40 | // 2 = line width, Plot::Square = marker style 41 | MyPlot.SetSeriesProperties("Sinewave", Plot::Blue, Plot::Solid, 2, Plot::Square); 42 | MyPlot.SetSeriesProperties("Cosinewave", Plot::Red, Plot::Solid, 2, Plot::Square); 43 | 44 | // Colours include 45 | // Red, Green, Blue, Yellow, Black, Magenta, Cyan, White 46 | 47 | // Markers include 48 | // Square, Diamond, Triangle, Circle, Cross, Plus, Star, DownwardTriangle, NoMarker 49 | 50 | // Line style 51 | // Solid, Dashed, Dotted, DashDot, DashDotDot 52 | 53 | } 54 | 55 | 56 | void loop() 57 | { 58 | double dY, dY2; 59 | float seconds; 60 | float frequency = 0.5; //Hz 61 | float phase = 3.141/2; 62 | 63 | seconds = (float)millis()/1000; 64 | 65 | dY = sin(2 * 3.141 * frequency * seconds); 66 | dY2 = cos(2 * 3.141 * frequency * seconds + phase); 67 | 68 | uint32_t Color1 = (Colors[0] << 16) | (Colors[1] << 8) | Colors[2]; 69 | uint32_t Color2 = (Colors[1] << 16) | (Colors[2] << 8) | Colors[0]; 70 | 71 | Colors[ColorIndex] = (Colors[ColorIndex] + 4) & 0xff; 72 | if (Colors[ColorIndex] == 0) 73 | { 74 | ColorIndex = (ColorIndex + 1) % 3; 75 | } 76 | 77 | //Send Data To MegunoLink Pro 78 | MyPlot.SendData(F("Sinewave"),dY, Color1); // Sinewave = series name, dY = data to plot 79 | MyPlot.SendData(F("Cosinewave"),dY2, Color2); // By wrapping strings in F("") we can save ram by storing strings in program memory 80 | 81 | 82 | delay(10); 83 | } 84 | -------------------------------------------------------------------------------- /src/utility/Message.cpp: -------------------------------------------------------------------------------- 1 | #include "Message.h" 2 | 3 | Message::Message(Print& rDestination) 4 | : MegunoLinkProtocol(F("MESSAGE"), rDestination) 5 | , m_Destination(Text) 6 | { 7 | 8 | } 9 | 10 | Message::Message(const char *channelName /*= NULL*/, Print &rDestination) 11 | : MegunoLinkProtocol(F("MESSAGE"), channelName, rDestination) 12 | , m_Destination(Text) 13 | { 14 | 15 | } 16 | 17 | Message::Message(const __FlashStringHelper* channelName, Print& rDestination) 18 | : MegunoLinkProtocol(F("MESSAGE"), channelName, rDestination) 19 | , m_Destination(Text) 20 | { 21 | 22 | } 23 | 24 | Message::Message(MessageDestination Destination, Print& rDestination) 25 | : MegunoLinkProtocol(F("MESSAGE"), rDestination) 26 | , m_Destination(Destination) 27 | { 28 | 29 | } 30 | 31 | Message::Message(MessageDestination Destination, const char *channelName /*= NULL*/, Print &rDestination) 32 | : MegunoLinkProtocol(F("MESSAGE"), channelName, rDestination) 33 | , m_Destination(Destination) 34 | { 35 | 36 | } 37 | 38 | Message::Message(MessageDestination Destination, const __FlashStringHelper *channelName, Print &rDestination) 39 | : MegunoLinkProtocol(F("MESSAGE"), channelName, rDestination) 40 | , m_Destination(Destination) 41 | { 42 | 43 | } 44 | 45 | void Message::Begin() 46 | { 47 | switch (m_Destination) 48 | { 49 | case Text: 50 | SendDataHeader(F("DATA")); 51 | break; 52 | case Speak: 53 | SendDataHeader(F("SPEAK")); 54 | break; 55 | case TextAndSpeak: 56 | SendDataHeader(F("SPEAK+DATA")); 57 | break; 58 | } 59 | } 60 | 61 | void Message::End() 62 | { 63 | SendDataTail(); 64 | } 65 | 66 | void Message::Send( const char *Message ) 67 | { 68 | Begin(); 69 | m_rDestination.print(Message); 70 | SendDataTail(); 71 | } 72 | 73 | void Message::Send( const __FlashStringHelper *Message ) 74 | { 75 | Begin(); 76 | m_rDestination.print(Message); 77 | SendDataTail(); 78 | } 79 | 80 | void Message::Clear() 81 | { 82 | SendDataHeader(F("CLEAR")); 83 | SendDataTail(); 84 | } 85 | 86 | void Message::LogTo(const __FlashStringHelper * Filename) 87 | { 88 | SendDataHeader(F("F")); 89 | m_rDestination.print(Filename); 90 | SendDataTail(); 91 | } 92 | 93 | void Message::LogTo(const char * Filename) 94 | { 95 | SendDataHeader(F("F")); 96 | m_rDestination.print(Filename); 97 | SendDataTail(); 98 | } 99 | 100 | void Message::LogTo(String &Filename) 101 | { 102 | SendDataHeader(F("F")); 103 | m_rDestination.print(Filename.c_str()); 104 | SendDataTail(); 105 | } 106 | 107 | void Message::StopLogging() 108 | { 109 | SendDataHeader(F("X")); 110 | SendDataTail(); 111 | } 112 | 113 | void Message::StartLogging() 114 | { 115 | SendDataHeader(F("F")); 116 | SendDataTail(); 117 | } 118 | 119 | void Message::Flush() 120 | { 121 | SendDataHeader(F("W")); 122 | SendDataTail(); 123 | } 124 | 125 | void Message::SendSeparator() 126 | { 127 | m_rDestination.print(F(": ")); 128 | } 129 | 130 | 131 | -------------------------------------------------------------------------------- /examples/Getting Started/SendCommandSequence/SendCommandSequence.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | == Example Description == 3 | This code helps demonstrate MegunoLink's message monkey visualizer, which lets MegunoLink send 4 | a series of commands to your Arduino sketch. In this example MegunoLink sends commands to 5 | turn on and off a digital output. 6 | 7 | == This Example Requires == 8 | * MegunoLink's Arduino library. Install it from MegunoLink by selecting 'Setup Arduino integration' 9 | from the gear menu. 10 | 11 | == More Information == 12 | * Download a free trial of MegunoLink: https://www.megunolink.com/download/ 13 | * Setup Arduino integration: https://www.megunolink.com/documentation/getting-started/arduino-integration/ 14 | * Serial command handler: https://www.megunolink.com/documentation/arduino-libraries/serial-command-handler/ 15 | 16 | == MegunoLink Interface == 17 | * Open the MegunoLink interface by selecting 'Send Command Sequence' from MegunoLink's 18 | Examples->Getting Started menu. 19 | 20 | == Serial Commands == 21 | This sketch implements the following serial commands: 22 | * !Out \r\n : Turns a digital output state. Port is the pin number to change. The 23 | output is turned on when State is 1 and off when state is 0. Port defaults to the built-in 24 | LED if it is missing. 25 | 26 | ************************************************************************************************/ 27 | 28 | #include "CommandHandler.h" // The serial command handler is defined in here. 29 | 30 | // The serial command handler. Receives serial data and dispatches 31 | // recognised commands to functions registered during setup. 32 | CommandHandler<> SerialCommandHandler; 33 | 34 | // ----------------------------------------------------------------------- 35 | // Command handlers. 36 | // These functions are called when a serial command is received. 37 | void Cmd_Out(CommandParameter &Parameters) 38 | { 39 | int State = Parameters.NextParameterAsInteger(0); 40 | int Port = Parameters.NextParameterAsInteger(LED_BUILTIN); 41 | 42 | pinMode(Port, OUTPUT); 43 | digitalWrite(Port, State); 44 | } 45 | 46 | // ----------------------------------------------------------------------- 47 | void setup() 48 | { 49 | Serial.begin(9600); 50 | Serial.println(F("MegunoLink Output Controller")); 51 | Serial.println(F("----------------------------")); 52 | 53 | // Setup the commands the handler will respond to. The first parameter 54 | // is the command name, the second is the function that will be called 55 | // when the command is received. Note that each command name is 56 | // inside F(""). This places the command text in program memory to 57 | // save RAM. Commands are case-sensitive. 58 | SerialCommandHandler.AddCommand(F("Out"), Cmd_Out); 59 | 60 | } 61 | 62 | void loop() 63 | { 64 | // Call the serial command handler's process function. It will receive 65 | // the serial data and call the registered function when a 66 | // recognized command is received. 67 | SerialCommandHandler.Process(); 68 | } 69 | -------------------------------------------------------------------------------- /examples/TimePlot/ENC28J60UDPPlotting/ENC28J60UDPPlotting.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | In this example we plot sinewave data on MegunoLink's Time Plot visualiser using a UDP connection 4 | and the Microchip ENC28J60 chip. 5 | 6 | More Information 7 | * http://www.megunolink.com/documentation/plotting/ 8 | 9 | This Example Requires: 10 | * The MegunoLink arduino library 11 | https://www.megunolink.com/documentation/arduino-integration/ 12 | * The EtherCard Library 13 | https://github.com/njh/EtherCard. 14 | 15 | MegunoLink Interface 16 | You can download a pre-made interface from: 17 | * https://github.com/Megunolink/MLP/raw/master/examples/TimePlot/ENC28J60UDPPlotting/ENC28J60UDPPlotting.mlpz 18 | 19 | You can find out more about MegunoLink and download a free trial from: 20 | * https://www.megunolink.com/ 21 | * https://www.megunolink.com/download/ 22 | ************************************************************************************************/ 23 | 24 | 25 | #include "MegunoLink.h" 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | ArduinoTimer PlotTimer; 32 | 33 | static byte mymac[] = { 0x1A,0x2B,0x3C,0x4D,0x5E,0x6F }; 34 | byte Ethernet::buffer[700]; 35 | const int dstPort PROGMEM = 8888; //Match this to the port selected in MegunoLink 36 | const int srcPort PROGMEM = 4321; 37 | 38 | const static uint8_t dstIP[] = { 255,255,255,255 }; //Broadcast address. You can replace this with a specific machines IP 39 | 40 | void setup() 41 | { 42 | Serial.begin(9600); 43 | Serial.println("MegunoLink Example"); 44 | 45 | // Change 'SS' to your Slave Select pin, if you arn't using the default pin 46 | if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0) 47 | { 48 | Serial.println("Failed to access Ethernet controller"); 49 | } 50 | if (!ether.dhcpSetup()) 51 | { 52 | Serial.println("DHCP failed"); 53 | } 54 | 55 | ether.printIp("IP: ", ether.myip); 56 | ether.printIp("GW: ", ether.gwip); 57 | ether.printIp("DNS: ", ether.dnsip); 58 | } 59 | 60 | 61 | void loop() 62 | { 63 | // We send udp packets every 200mS. Because it relies on the network interface its hard 64 | // to have reliable timing. 65 | if (PlotTimer.TimePassed_Milliseconds(200)) 66 | { 67 | // The commands for MegunoLink are assembled in the Message buffer 68 | // then sent using sendUdp. 69 | FixedStringBuffer<100> Message; 70 | TimePlot MyPlot("", Message); 71 | 72 | double dY, dY2; 73 | float seconds; 74 | float frequency = 0.1; //Hz 75 | float phase = 3.141 / 2; 76 | 77 | seconds = (float)millis() / 1000; 78 | 79 | dY = sin(2 * 3.141 * frequency * seconds); 80 | dY2 = cos(2 * 3.141 * frequency * seconds + phase); 81 | 82 | //Send Data To MegunoLink Pro 83 | MyPlot.SendData(F("Sinewave"), dY); // Sinewave = series name, dY = data to plot 84 | MyPlot.SendData(F("Cosinewave"), dY2); // By wrapping strings in F("") we can save ram by storing strings in program memory 85 | ether.sendUdp(Message, Message.length(), srcPort, dstIP, dstPort); 86 | } 87 | } -------------------------------------------------------------------------------- /examples/TimePlot/TwoAxisPlot/TwoAxisPlot.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************ 2 | Example Description 3 | In this example we use MegunoLink's Time Plot visualiser to plot sinewave data using two different 4 | y-axes. 5 | 6 | More Information 7 | * http://www.megunolink.com/documentation/plotting/ 8 | * https://www.megunolink.com/documentation/arduino-libraries/arduino-timer/ 9 | 10 | This Example Requires: 11 | * The MegunoLink arduino library https://www.megunolink.com/documentation/arduino-integration/ 12 | 13 | MegunoLink Interface 14 | You can download a pre-made interface from here: 15 | https://github.com/Megunolink/MLP/raw/master/examples/TimePlot/TwoAxisPlot/TwoAxisPlot.mlpz 16 | 17 | You can find out more about MegunoLink and download a free trial from here 18 | https://www.megunolink.com/ 19 | https://www.megunolink.com/download/ 20 | ************************************************************************************************/ 21 | 22 | 23 | #include "MegunoLink.h" 24 | #include "ArduinoTimer.h" 25 | 26 | // Uncomment if you would like to use plotting channels 27 | // TimePlot MyPlot("Waveforms"); //"Waveforms" = the taget plotting channel (remember to select this in megunolink) 28 | 29 | TimePlot MyPlot; //no channel selected 30 | 31 | ::ArduinoTimer PlotPropertiesTimer; 32 | ::ArduinoTimer PlotSendTimer; 33 | 34 | void setup() 35 | { 36 | Serial.begin(115200); 37 | SendPlotProperties(); 38 | } 39 | 40 | 41 | void loop() 42 | { 43 | double dY, dY2; 44 | float seconds; 45 | float frequency = 0.5; //Hz 46 | float phase = 3.141 / 2; 47 | 48 | //Send plotting data every 100mS 49 | if (PlotSendTimer.TimePassed_Milliseconds(100)) 50 | { 51 | seconds = (float)millis() / 1000; 52 | 53 | dY = sin(2 * 3.141 * frequency * seconds); 54 | dY2 = cos(2 * 3.141 * frequency * seconds + phase); 55 | 56 | //Send Data To MegunoLink Pro 57 | //"Sinewave" = series name, Plot::Blue = line colour, 2 = line width, Plot::Square = marker style 58 | MyPlot.SendData(F("Sinewave"), dY, Plot::Blue, Plot::Solid, 2, Plot::Square, Plot::LeftAxis); // Sinewave = series name, dY = data to plot 59 | MyPlot.SendData(F("Cosinewave"), dY2, Plot::Red, Plot::Solid, 2, Plot::Square, Plot::RightAxis); // By wrapping strings in F("") we can save ram by storing strings in program memory 60 | 61 | // Colours include 62 | // Red, Green, Blue, Yellow, Black, Magenta, Cyan, White 63 | 64 | // Markers include 65 | // Square, Diamond, Triangle, Circle, Cross, Plus, Star, DownwardTriangle, NoMarker 66 | 67 | // Line style 68 | // Solid, Dashed, Dotted, DashDot, DashDotDot 69 | 70 | // Axis options 71 | // LeftAxis, RightAxis, DefaultAxis 72 | 73 | } 74 | 75 | //Send plotting style message every 10000mS 76 | if (PlotPropertiesTimer.TimePassed_Milliseconds(10000)) 77 | { 78 | SendPlotProperties(); 79 | } 80 | } 81 | 82 | 83 | void SendPlotProperties() 84 | { 85 | MyPlot.SetTitle("Sine and Cosine Function Waveforms"); 86 | MyPlot.SetXLabel("Time"); 87 | MyPlot.SetYLabel("Amplitude"); 88 | MyPlot.SetY2Label("Amplitude 2"); 89 | MyPlot.SetYRange(-1.5, 5); 90 | MyPlot.SetY2Range(-5, 1.5); 91 | MyPlot.SetY2Visible(); 92 | } -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ArduinoTimer KEYWORD1 2 | Reset KEYWORD2 3 | EllapsedMilliseconds KEYWORD2 4 | EllapsedSeconds KEYWORD2 5 | TimePassed_Milliseconds KEYWORD2 6 | TimePassed_Seconds KEYWORD2 7 | TimePassed_Minutes KEYWORD2 8 | TimePassed_Hours KEYWORD2 9 | StartTime KEYWORD2 10 | CircularBuffer KEYWORD1 11 | ElementSize KEYWORD2 12 | IsEmpty KEYWORD2 13 | Add KEYWORD2 14 | Add KEYWORD2 15 | Head KEYWORD2 16 | Tail KEYWORD2 17 | PopTail KEYWORD2 18 | DropRecords KEYWORD2 19 | Clear KEYWORD2 20 | CountStored KEYWORD2 21 | MaxSize KEYWORD2 22 | GetTailIndex KEYWORD2 23 | Dump KEYWORD2 24 | ForwardIterator KEYWORD1 25 | CurrentValue KEYWORD2 26 | CurrentIndex KEYWORD2 27 | Next KEYWORD2 28 | AtEnd KEYWORD2 29 | Previous KEYWORD2 30 | ReverseIterator KEYWORD1 31 | CommandHandler KEYWORD1 32 | Process KEYWORD2 33 | AddCommand KEYWORD2 34 | SetDefaultHandler KEYWORD2 35 | ClearCommands KEYWORD2 36 | AddVariable KEYWORD2 37 | DispatchCommand KEYWORD2 38 | CommandParameter KEYWORD1 39 | GetSource KEYWORD2 40 | NextParameter KEYWORD2 41 | RemainingParameters KEYWORD2 42 | NextParameterAsInteger KEYWORD2 43 | NextParameterAsLong KEYWORD2 44 | NextParameterAsUnsignedLong KEYWORD2 45 | NextParameterAsDouble KEYWORD2 46 | DataStore KEYWORD1 47 | Send KEYWORD2 48 | EEPROMStore KEYWORD1 49 | Load KEYWORD2 50 | Save KEYWORD2 51 | Reset KEYWORD2 52 | ExponentialFilter KEYWORD1 53 | SetWeight KEYWORD2 54 | GetWeight KEYWORD2 55 | Current KEYWORD2 56 | Filter KEYWORD2 57 | SpecialParameters KEYWORD1 58 | CurrentTime KEYWORD2 59 | 60 | InterfacePanel KEYWORD1 61 | SetText KEYWORD2 62 | SetProgress KEYWORD2 63 | SetNumber KEYWORD2 64 | SetListIndex KEYWORD2 65 | SetListValue KEYWORD2 66 | SetCheck KEYWORD2 67 | ShowControl KEYWORD2 68 | HideControl KEYWORD2 69 | ClearCheck KEYWORD2 70 | CallCommand KEYWORD2 71 | GetValue KEYWORD2 72 | 73 | Map KEYWORD1 74 | SendData KEYWORD2 75 | 76 | Message KEYWORD1 77 | Begin KEYWORD2 78 | End KEYWORD2 79 | Send KEYWORD2 80 | Clear KEYWORD2 81 | Flush KEYWORD2 82 | StartLogging KEYWORD2 83 | LogTo KEYWORD2 84 | StopLogging KEYWORD2 85 | 86 | Table KEYWORD1 87 | SendData KEYWORD2 88 | SetDescription KEYWORD2 89 | ClearAllRows KEYWORD2 90 | ClearRow KEYWORD2 91 | GetData KEYWORD2 92 | 93 | TimePlot KEYWORD1 94 | SendData KEYWORD2 95 | FitXScale KEYWORD2 96 | FitYScale KEYWORD2 97 | FitY2Scale KEYWORD2 98 | FitScale KEYWORD2 99 | SendFloatData KEYWORD2 100 | SetCursorVisibility KEYWORD2 101 | SetCursorPosition KEYWORD2 102 | SetCursorPositionToNow KEYWORD2 103 | 104 | XYPlot KEYWORD1 105 | SendData KEYWORD2 106 | 107 | Report KEYWORD1 108 | EnablePeriodicReports KEYWORD2 109 | GenerateNow KEYWORD2 110 | 111 | RecordTable KEYWORD1 112 | AddRow KEYWORD2 113 | AddRowFromArray KEYWORD2 114 | AddRowWithIds KEYWORD2 115 | AddRowFromArrayWithIds KEYWORD2 116 | UpdateRow KEYWORD2 117 | UpdateRowFromArray KEYWORD2 118 | UpdateRowFromArrayWithIds KEYWORD2 119 | SetValue KEYWORD2 120 | ClearAllRows KEYWORD2 121 | ClearRow KEYWORD2 122 | SetNumberOfDecimalPlaces KEYWORD2 123 | 124 | Audio KEYWORD1 125 | Speak KEYWORD2 126 | PlayAudioClip KEYWORD2 127 | Stop KEYWORD2 128 | 129 | Monkey KEYWORD1 130 | ClearTriggers KEYWORD2 131 | SetTrigger KEYWORD2 132 | ClearTrigger KEYWORD2 133 | -------------------------------------------------------------------------------- /src/utility/CommandParameter.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandParameter.h" 2 | 3 | CommandParameter::CommandParameter(Print &rSourceStream, char *pchBuffer, uint8_t uFirstParameter, IPAddress* pSender) 4 | : Response(rSourceStream) 5 | { 6 | m_pchBuffer = pchBuffer; 7 | m_uNextParameter = uFirstParameter; 8 | m_pSender = pSender; 9 | } 10 | 11 | const char *CommandParameter::NextParameter() 12 | { 13 | if (m_pchBuffer[m_uNextParameter] == '\0') 14 | return NULL; 15 | 16 | // Null terminate the next parameter 17 | char *pchParameter = m_pchBuffer + m_uNextParameter; 18 | char *pchEnd = pchParameter; 19 | while (*pchEnd != ' ' && *pchEnd != '\0') 20 | { 21 | ++pchEnd; 22 | ++m_uNextParameter; 23 | } 24 | 25 | if (*pchEnd != '\0') 26 | { 27 | ++m_uNextParameter; 28 | *pchEnd = '\0'; 29 | } 30 | 31 | return pchParameter; 32 | } 33 | 34 | const char * CommandParameter::RemainingParameters() 35 | { 36 | return m_pchBuffer + m_uNextParameter; 37 | } 38 | 39 | int CommandParameter::NextParameterAsInteger( int nDefault /*= -1*/ ) 40 | { 41 | const char *pchParameter = NextParameter(); 42 | if (pchParameter == NULL) 43 | return nDefault; 44 | 45 | return atoi(pchParameter); 46 | } 47 | 48 | long CommandParameter::NextParameterAsLong( long nDefault /*= -1*/ ) 49 | { 50 | const char *pchParameter = NextParameter(); 51 | if (pchParameter == NULL) 52 | return nDefault; 53 | 54 | return atol(pchParameter); 55 | } 56 | 57 | unsigned long CommandParameter::NextParameterAsUnsignedLong( unsigned long nDefault /*= -1*/ ) 58 | { 59 | const char *pchParameter = NextParameter(); 60 | if (pchParameter == NULL) 61 | return nDefault; 62 | 63 | return strtoul(pchParameter, NULL, 10); 64 | } 65 | 66 | double CommandParameter::NextParameterAsDouble( double fDefault /*= 0.0*/ ) 67 | { 68 | const char *pchParameter = NextParameter(); 69 | if (pchParameter == NULL) 70 | return fDefault; 71 | 72 | return atof(pchParameter); 73 | } 74 | 75 | uint8_t CommandParameter::NextParameterAsU8FromHex(uint8_t uDefault) 76 | { 77 | return NextParameterAsU32FromHex(uDefault) & 0xff; 78 | } 79 | 80 | uint16_t CommandParameter::NextParameterAsU16FromHex(uint16_t uDefault) 81 | { 82 | return NextParameterAsU32FromHex(uDefault) & 0xffff; 83 | } 84 | 85 | uint32_t CommandParameter::NextParameterAsU32FromHex(uint32_t uDefault) 86 | { 87 | const char* pchParameter = NextParameter(); 88 | if (pchParameter == NULL) 89 | return uDefault; 90 | uint32_t uValue = 0; 91 | while (*pchParameter != '\0') 92 | { 93 | uValue = (uValue << 4) | HexValueOf(*pchParameter++); 94 | } 95 | 96 | return uValue; 97 | } 98 | 99 | bool CommandParameter::GetSenderAddress(IPAddress& rAddress) 100 | { 101 | if (m_pSender != nullptr) 102 | { 103 | rAddress = *m_pSender; 104 | } 105 | return m_pSender != nullptr; 106 | } 107 | 108 | uint8_t CommandParameter::HexValueOf(char ch) 109 | { 110 | if (ch >= '0' && ch <= '9') 111 | { 112 | return ch - '0'; 113 | } 114 | 115 | if (ch >= 'a' && ch <= 'f') 116 | { 117 | return ch - 'a' + 10; 118 | } 119 | 120 | if (ch >= 'A' && ch <= 'F') 121 | { 122 | return ch - 'A' + 10; 123 | } 124 | 125 | return 0; 126 | } -------------------------------------------------------------------------------- /src/utility/TestReport.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MegunoLinkProtocol.h" 3 | 4 | class TestReport : public MegunoLinkProtocol 5 | { 6 | public: 7 | TestReport(Print &rDestination = Serial); 8 | 9 | void ReportResult(int TestId, bool bPass); 10 | template void ReportResult(int TestId, bool bPass, TData Data); 11 | 12 | void ReportResult(const char *pchName, bool bPass); 13 | void ReportResult(const __FlashStringHelper *pchName, bool bPass); 14 | 15 | template void ReportResult(const char *pchName, bool bPass, TData Data); 16 | template void ReportResult(const __FlashStringHelper *pchName, bool bPass, TData Data); 17 | 18 | void Pass(const char *pchName); 19 | void Pass(const __FlashStringHelper *pchName); 20 | template void Pass(const char *pchName, TData Data); 21 | template void Pass(const __FlashStringHelper *pchName, TData Data); 22 | 23 | void Fail(const char *pchName); 24 | void Fail(const __FlashStringHelper *pchName); 25 | template void Fail(const char *pchName, TData Data); 26 | template void Fail(const __FlashStringHelper *pchName, TData Data); 27 | 28 | void StartingTest(); 29 | void TestComplete(); 30 | 31 | private: 32 | void SendFirstPart(bool bPass, const char * pchName); 33 | void SendFirstPart(bool bPass, const __FlashStringHelper * pchName); 34 | void SendFirstPart(bool bPass, int nTestId); 35 | void SendFirstPart(bool bPass); 36 | }; 37 | 38 | template 39 | inline void TestReport::ReportResult(int TestId, bool bPass, TData Data) 40 | { 41 | SendFirstPart(bPass, TestId); 42 | m_rDestination.print('|'); 43 | m_rDestination.print(Data); 44 | SendDataTail(); 45 | } 46 | 47 | template 48 | inline void TestReport::ReportResult(const char * pchName, bool bPass, TData Data) 49 | { 50 | SendFirstPart(bPass, pchName); 51 | m_rDestination.print('|'); 52 | m_rDestination.print(Data); 53 | SendDataTail(); 54 | } 55 | 56 | template 57 | inline void TestReport::ReportResult(const __FlashStringHelper * pchName, bool bPass, TData Data) 58 | { 59 | SendFirstPart(bPass, pchName); 60 | m_rDestination.print('|'); 61 | m_rDestination.print(Data); 62 | SendDataTail(); 63 | } 64 | 65 | template 66 | inline void TestReport::Pass(const char * pchName, TData Data) 67 | { 68 | SendFirstPart(true, pchName); 69 | m_rDestination.print('|'); 70 | m_rDestination.print(Data); 71 | SendDataTail(); 72 | } 73 | 74 | template 75 | inline void TestReport::Pass(const __FlashStringHelper * pchName, TData Data) 76 | { 77 | SendFirstPart(true, pchName); 78 | m_rDestination.print('|'); 79 | m_rDestination.print(Data); 80 | SendDataTail(); 81 | } 82 | 83 | template 84 | inline void TestReport::Fail(const char * pchName, TData Data) 85 | { 86 | SendFirstPart(false, pchName); 87 | m_rDestination.print('|'); 88 | m_rDestination.print(Data); 89 | SendDataTail(); 90 | } 91 | 92 | template 93 | inline void TestReport::Fail(const __FlashStringHelper * pchName, TData Data) 94 | { 95 | SendFirstPart(false, pchName); 96 | m_rDestination.print('|'); 97 | m_rDestination.print(Data); 98 | SendDataTail(); 99 | } 100 | --------------------------------------------------------------------------------