Created
November 12, 2021 20:45
-
-
Save MRtecno98/6f7b8e80c335ba5f9ac8169932ddbead to your computer and use it in GitHub Desktop.
Arduino serial panel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef LCDMENU | |
#define LCDMENU | |
void setCursor(int, int); | |
void incrementSelected(); | |
void decrementSelected(); | |
void print_options(boolean); | |
void print_options(boolean, int); | |
void print_options_fullscreen(); | |
void allocate_options(); | |
int *options; | |
int options_n = 0; | |
int selected_option = 0; | |
void (*active_handler)(boolean, boolean, boolean, boolean); | |
void nothing_handler(boolean, boolean, boolean, boolean); | |
int cursor_column = 0; | |
int cursor_line = 0; | |
void nothing_handler(boolean up, boolean down, boolean back, boolean enter) {} | |
void print_options_fullscreen() { | |
lcd.clear(); | |
setCursor(0, 0); | |
print_options(true, (selected_option % 2) == 0 ? selected_option : selected_option - 1); | |
} | |
void print_options(boolean double_l) { | |
print_options(double_l, 0); | |
} | |
void setCursor(int col, int line) { | |
cursor_column = col; | |
cursor_line = line; | |
lcd.setCursor(col, line); | |
} | |
void incrementSelected() { | |
selected_option = selected_option == options_n-1 ? selected_option : selected_option+1; | |
} | |
void decrementSelected() { | |
selected_option = selected_option == 0 ? selected_option : selected_option-1; | |
} | |
void print_options(boolean double_l, int offset) { | |
for(int i = offset; i < (double_l ? offset+2 : offset+1); i++) { | |
lcd.print((selected_option == i ? "> " : "")); | |
int index = (options)[i]; | |
lcd.print(strings[index]); | |
setCursor(0, cursor_line == 0 ? 1 : 0); | |
} | |
} | |
void allocate_options() { | |
free(options); | |
options = malloc(sizeof(int *) * options_n); | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PACKETS | |
#define PACKETS | |
class Packet { | |
public: | |
virtual byte Packet::getIdentifier() = 0; | |
virtual const byte* Packet::getPayload() = 0; | |
virtual int Packet::getPayloadSize() = 0; | |
}; | |
class BasePacket : public Packet { | |
protected: | |
byte identifier; | |
int packetsize; | |
byte* payload; | |
public: | |
BasePacket(byte, int, const byte*); | |
~BasePacket(); | |
byte getIdentifier(); | |
const byte* getPayload(); | |
int getPayloadSize(); | |
}; | |
BasePacket::BasePacket(byte identifier, int payloadsize, const byte* payload) { | |
this->identifier = identifier; | |
this->packetsize = payloadsize; | |
this->payload = payload; | |
} | |
byte BasePacket::getIdentifier() { | |
return this->identifier; | |
} | |
int BasePacket::getPayloadSize() { | |
return this->packetsize; | |
} | |
const byte* BasePacket::getPayload() { | |
return this->payload; | |
} | |
BasePacket::~BasePacket() { | |
delete (*this).payload; | |
} | |
class PrintPacket : public BasePacket { | |
public: | |
PrintPacket(String message); | |
private: | |
String message; | |
static int getPacketSizeFor(String); | |
static byte* constructPacket(String); | |
}; | |
PrintPacket::PrintPacket(String message) : BasePacket(PRINT_PACKET, PrintPacket::getPacketSizeFor(message), PrintPacket::constructPacket(message)) { | |
this->message = message; | |
} | |
static int PrintPacket::getPacketSizeFor(String s) { | |
return s.length() + 1; | |
} | |
static byte* PrintPacket::constructPacket(String s) { | |
int payloadsize = PrintPacket::getPacketSizeFor(s); | |
byte* payload = new byte[payloadsize]; | |
payload[0] = s.length(); | |
for(int i = 0; i < s.length(); i++) payload[i+1] = s[i]; | |
return payload; | |
} | |
class RestartPacket : public BasePacket { | |
public: | |
RestartPacket() : BasePacket(RESTART_PACKET, 0, NULL) {} | |
}; | |
class ServerListPacket : public BasePacket { | |
public: | |
ServerListPacket() : BasePacket(LIST_PACKET, 0, NULL) {} | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <LiquidCrystal.h> | |
#include <errno.h> | |
#include <avr/wdt.h> | |
#define awr_reset() wdt_enable(WDTO_30MS); wdt_reset() | |
#define MAX_MEM 2048 | |
void restart(); | |
String strings[] = { | |
"View actions", | |
"Send serial", | |
"Emulate Error", | |
"Restart System", | |
"System stats", | |
"Main menu", | |
}; | |
#include "protocol.h" | |
Proxy* proxy; | |
LiquidCrystal lcd(2, 3, 4, //Reg.Sel., R/W, E | |
5, 6, 7, 8, //D0-D3 | |
9, 10, 11, 12); //D4-D7 | |
#include "lcdmenu.h" | |
#define BUTTONS_N 4 | |
boolean precedent_pulsant[] = {false, false, false, false}; | |
int buttons[] = {A5, A4, A3, A2}; | |
void setup() { | |
lcd.begin(16, 2); | |
Serial.begin(9600); | |
pinMode(13, OUTPUT); | |
for(int i = 0; i < BUTTONS_N; i++) pinMode(buttons[i], INPUT); | |
proxy = new Proxy(); | |
if(!proxy->establish_connection()) { | |
message_menu("Waiting for", "connection..."); | |
proxy->start_connection(); | |
} | |
message_menu("Connection", "established", 1500); | |
main_menu(); | |
} | |
void loop() { | |
if(errno) errno_menu(); | |
tickHandlers(); | |
delay(100); | |
} | |
void restart() { | |
proxy->send_packet(new RestartPacket()); | |
awr_reset(); | |
} | |
void tickHandlers() { | |
boolean states[] = {false, false, false, false}; | |
for(int i = 0; i < BUTTONS_N; i++) { | |
bool actual_state = digitalRead(buttons[i]); | |
if(actual_state != precedent_pulsant[i]) { | |
states[i] = actual_state; | |
precedent_pulsant[i] = actual_state; | |
}else states[i] = false; | |
} | |
(*active_handler)(states[0], states[1], states[2], states[3]); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import serial, traceback, sys | |
ENABLE_BYTE = b'\xab' | |
START_BYTE = b'\xff' | |
class Processor() : | |
def restart(self) : | |
pass | |
def is_processable(self, identifier) : | |
return True | |
def process(self, controller) : | |
pass | |
class PrintProcessor(Processor) : | |
def is_processable(self, identifier) : | |
return identifier == b'\x00' | |
def process(self, controller) : | |
size = int.from_bytes(controller._ser.read(1), 'little') | |
text = controller._ser.read(size) | |
print("[PrintPacket] " + text.decode()) | |
class RestartProcessor(Processor) : | |
def is_processable(self, identifier) : | |
return identifier == b'\xfe' | |
def process(self, controller) : | |
print("Received connection restart request") | |
controller.restart_connection() | |
print("Connection restarted") | |
class Controller() : | |
def __start_connection(self) : | |
self._ser = serial.Serial(self.port, 9600) | |
while not self._ser.in_waiting : | |
pass | |
assert self._ser.read(1) == START_BYTE | |
self._ser.write(ENABLE_BYTE) | |
assert self._ser.read(1) == ENABLE_BYTE | |
def __init__(self, port, *processors) : | |
self.port = port | |
self.processors = [] | |
self.add_processors(*processors) | |
self.__start_connection() | |
def add_processors(self, *processors) : | |
self.processors += [proc if isinstance(proc, Processor) else \ | |
proc() if issubclass(proc, Processor) else None \ | |
for proc in processors] | |
self.processors = [p for p in self.processors if p != None] | |
def select_processors(self, identifier) : | |
return [proc.process(self) for proc in self.processors \ | |
if proc.is_processable(identifier)] | |
def restart_connection(self) : | |
self.close() | |
self.__start_connection() | |
def stop_loop(self) : | |
self.ongoing = False | |
def main_loop(self) : | |
self.ongoing = True | |
while self.ongoing : | |
if self._ser.in_waiting : | |
# print(self._ser.read(self._ser.in_waiting)) | |
identifier = self._ser.read(1) | |
self.select_processors(identifier) | |
def close(self) : | |
self._ser.close() | |
def __del__(self) : | |
self.close() | |
def main() : | |
port = input("Select port(Default: COM4): ") | |
port = port if port else "COM4" | |
contr = Controller(port, PrintProcessor, RestartProcessor) | |
print("Connection establised") | |
while True : | |
try : | |
contr.main_loop() | |
except KeyboardInterrupt : | |
act = input("Try to reconnect or close server?(r/c): ").lower().strip() | |
if act == "r" : | |
contr.restart_connection() | |
print("Connection restarted") | |
continue | |
elif act == "c" : | |
contr.ongoing = False | |
break | |
except Exception as e: | |
raise Exception("Error while processing packet") from e | |
break | |
if __name__ == "__main__" : | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PROCESSORS | |
#define PROCESSORS | |
#include "protocol.h" | |
#include "packets.h" | |
class Response { | |
protected: | |
Response(); | |
}; | |
class Processor { | |
public: | |
virtual boolean is_processable(byte identifier) = 0; | |
virtual Response* process(Proxy* proxy) = 0; | |
}; | |
class ServerListProcessor : public Processor { | |
public: | |
boolean is_processable(byte identifier); | |
Response* process(Proxy* proxy); | |
class ServerListResponse : public Response { | |
private: | |
String* servers; | |
int len; | |
public: | |
ServerListResponse(const String*, int); | |
~ServerListResponse(); | |
String* getServerList(); | |
int getServersCount(); | |
}; | |
}; | |
boolean ServerListProcessor::is_processable(byte identifier) { | |
return identifier == LIST_PACKET; | |
} | |
Response* ServerListProcessor::process(Proxy* proxy) { | |
byte servlen = Serial.read(); | |
String* names = new String[servlen]; | |
for(int i = 0; i < servlen; i++) { | |
byte strlength = Serial.read(); | |
char* str = new char[strlength]; | |
for(int j = 0; j < strlength; j++) { | |
str[j] = Serial.read(); | |
} | |
String s(str); | |
names[i] = s; | |
} | |
ServerListProcessor::ServerListResponse response(names, servlen); | |
return &response; | |
} | |
ServerListProcessor::ServerListResponse::ServerListResponse(const String* servers, int len) { | |
this->servers = servers; | |
this->len = len; | |
} | |
ServerListProcessor::ServerListResponse::~ServerListResponse() { | |
delete this->servers; | |
} | |
String* ServerListProcessor::ServerListResponse::getServerList() { | |
return this->servers; | |
} | |
int ServerListProcessor::ServerListResponse::getServersCount() { | |
return this->len; | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PROTOCOL | |
#define PROTOCOL | |
#define START_PACKET 0xff | |
#define ENABLE_PACKET 0xab | |
#define RESTART_PACKET 0xfe | |
#define PRINT_PACKET 0x00 | |
#define LIST_PACKET 0x01 | |
#include <HardwareSerial.h> | |
#include "packets.h" | |
class Proxy { | |
public: | |
Proxy::start_connection(); | |
Proxy::send_packet(byte identifier, int payload_size, byte* payload); | |
Proxy::send_packet(Packet* p); | |
bool Proxy::establish_connection(); | |
}; | |
#include "processors.h" | |
Proxy::start_connection() { | |
Serial.write(START_PACKET); | |
while(!this->establish_connection()) {} | |
} | |
bool Proxy::establish_connection() { | |
if(!Serial.available()) return false; | |
uint8_t control = Serial.read(); | |
if(control == 0xab) { | |
Serial.write(control); | |
return true; | |
}else return false; | |
} | |
Proxy::send_packet(byte identifier, int payload_size, byte* payload) { | |
Serial.write(identifier); | |
for(int i = 0; i < payload_size; i++) Serial.write(payload[i]); | |
} | |
Proxy::send_packet(Packet* p) { | |
this->send_packet(p->getIdentifier(), p->getPayloadSize(), p->getPayload()); | |
delete p; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment