├── 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 | 
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 |
--------------------------------------------------------------------------------