├── 20230723_215547.jpg ├── 20230813_010139.jpg ├── 20230813_105127.jpg ├── CommunicationSwitch-HOWTO ├── MESH-Network-Inspiration.txt ├── Peer2Peer-Routing-Messages.txt ├── README.md ├── aeskey_demo2 └── aeskey_demo2.ino ├── demo3.jpg ├── demo4.jpg ├── espnow-functions ├── Setup1_st7789_130x320.h ├── espnow-functions.ino └── offgrid_intro.h ├── espnow-receiver-code ├── Setup1_st7789_130x320.h ├── espnow-receiver-code.ino └── offgrid_intro.h ├── k9code ├── Setup1_st7789_130x320.h ├── k9-1.docx ├── k9code.ino └── offgrid_intro.h └── sulfuroid_A_close_portrait_of_a_modern_dark_purple_hair_glamour_3bb2f303-f06c-4190-96b3-a40f14463b5a.png /20230723_215547.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccadic/offgridkom/6d47e3ac04f375781be3d2fc443cb7e00604a6a9/20230723_215547.jpg -------------------------------------------------------------------------------- /20230813_010139.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccadic/offgridkom/6d47e3ac04f375781be3d2fc443cb7e00604a6a9/20230813_010139.jpg -------------------------------------------------------------------------------- /20230813_105127.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccadic/offgridkom/6d47e3ac04f375781be3d2fc443cb7e00604a6a9/20230813_105127.jpg -------------------------------------------------------------------------------- /CommunicationSwitch-HOWTO: -------------------------------------------------------------------------------- 1 | 2 | 3 | Scanning Available Protocols: 4 | 5 | Use the ESP32 microcontroller's built-in capabilities to scan for nearby WiFi networks and ESP-NOW devices. 6 | Employ the RAKWireless RAK3172 to scan for available LoRa and LoRaWAN signals. 7 | If Bluetooth is enabled, scan for nearby Bluetooth devices too. 8 | Defining and Testing Priorities: 9 | 10 | After scanning, rank available protocols based on the set priorities (ESP-NOW, LoRa, LoRaWAN, WiFi, smartphone). 11 | Test the device's ability to switch between protocols based on signal availability and quality. 12 | Implementing Selection Process: 13 | 14 | Choose the highest-priority protocol based on scanning results. 15 | Implement switch-over routines for the device to change protocols if the chosen signal weakens or becomes unavailable. 16 | Integration with a Smartphone: 17 | 18 | If paired with a smartphone via Bluetooth, enable the device to use the smartphone's cellular network as a gateway. This might require the development of a simple mobile app to aid communication between the device and smartphone. 19 | User Interface (UI): 20 | 21 | On the ST7789 screen, clearly display the protocol currently in use by the device. 22 | In the menu system, allow users to set preferences, such as enforcing the use of a specific protocol or changing protocol priority order. 23 | Testing: 24 | 25 | Thoroughly test in various environments and scenarios to ensure the device correctly switches between protocols based on priorities and availability. 26 | Overall, this hybrid communication approach provides significant flexibility and resilience to your device. With the ability to switch between different protocols, the device can maintain near-constant connectivity, which is essential for such a communicator. 27 | -------------------------------------------------------------------------------- /MESH-Network-Inspiration.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | A radio mesh network (or wireless mesh network) is a network architecture where nodes are all dynamically interconnected and can cooperate with each other to route data packets. The main technical characteristics of this type of network are: 4 | 5 | 1. **Dynamic Topology**: In a mesh network, nodes can join or leave the network at any time. Therefore, the network topology is dynamic and self-organized. 6 | 7 | 2. **Multi-Hops**: Data packets can be transmitted from a source node to a destination node using several intermediaries. This is one of the main features that distinguishes a mesh network from point-to-point or star networks. 8 | 9 | 3. **Routing**: Nodes in a mesh network have the capability to perform routing. They can decide the best path to route a packet based on various criteria (e.g., number of hops, signal quality). 10 | 11 | 4. **Redundancy**: Due to its meshed topology, the network offers redundancy. If one path or node fails, the network can reroute packets via another path. 12 | 13 | 5. **Adaptability**: Mesh networks are highly adaptable to environmental or topology changes, making them ideal for situations where infrastructure might be unpredictable or constantly evolving. 14 | 15 | 6. **Security**: Mesh networks can be configured to offer enhanced security, including data encryption, node authentication, etc. 16 | 17 | 7. **Extended Range**: Using the multi-hop principle, a mesh network can cover a large geographic area, with each node acting as a relay to extend the network's reach. 18 | 19 | 8. **Density and Capacity**: Mesh networks can handle a large number of nodes, which is ideal for applications such as smart cities or large events. 20 | 21 | 9. **Underlying Technologies**: Radio mesh networks can be implemented using various radio technologies, including WiFi, Zigbee, LoRa, among others. 22 | 23 | 10. **Varied Applications**: Due to their unique characteristics, mesh networks are used in a variety of applications, from surveillance systems to sensor networks to connectivity solutions in rural areas. 24 | 25 | In summary, radio mesh networks offer flexibility, robustness, and adaptability that make them ideal for many scenarios where traditional connectivity might be challenging. 26 | 27 | --- 28 | -------------------------------------------------------------------------------- /Peer2Peer-Routing-Messages.txt: -------------------------------------------------------------------------------- 1 | Peer 2 Peer protocole ideas 2 | First concept 3 | 4 | Here is a general strategy you might adopt: 5 | 6 | Node Discovery and Network Maintenance: 7 | 8 | Each node should be capable of discovering other nodes nearby through WiFi or radio communication. 9 | Nodes should periodically share their routing tables to keep the network topology updated. 10 | Routing Table: 11 | 12 | Each node maintains a routing table that contains information about neighboring nodes and the shortest paths to reach other nodes. 13 | ERC-20 addresses can be used as unique identifiers for each node. 14 | Message Transmission: 15 | 16 | Messages contain the ERC-20 destination address, the source, the message content, and perhaps a type of TTL (Time-to-Live) to prevent messages from circulating indefinitely in the network. 17 | Each node checks the message's destination. If the node is the destination, it processes the message; otherwise, it forwards it to the best neighboring node based on its routing table. 18 | The choice of the "best" neighboring node might be based on proximity, signal quality, number of hops, etc. 19 | Mode of Transmission Selection: 20 | 21 | Each node decides to transmit a message via WiFi or radio based on factors such as range, availability, congestion, etc. 22 | If a node has internet access, it could use that to transmit messages to nodes that are far away or out of direct range, perhaps using a relay server or a messaging service. 23 | Message Relay: 24 | 25 | If a message needs to reach a node out of direct range, intermediary nodes act as relays to route the message to its destination. 26 | This requires robust routing logic to avoid loops and ensure message delivery. 27 | Reliability and Acknowledgment: 28 | 29 | You'd probably want to implement some sort of acknowledgment to confirm the reception of messages. 30 | This might include techniques to handle retransmissions in case of delivery failure. 31 | Security: 32 | 33 | The use of ERC-20 addresses is an interesting idea, especially if you incorporate some form of digital signature to authenticate and secure the messages. 34 | Messages can be signed using the private key corresponding to the ERC-20 address, and other nodes can verify this signature with the address/pubkey. 35 | Scaling and Congestion Management: 36 | 37 | In a large network with many nodes, congestion can become an issue. 38 | Techniques like flow control, rate limiting, and message prioritization might be necessary. 39 | Interfacing with Other Networks: 40 | 41 | If certain nodes have additional interconnection capabilities (e.g., satellite link, LTE), they could act as gateways to route traffic to and from other networks. 42 | Tests and Simulations: 43 | 44 | Before deploying, it would be beneficial to simulate the protocol in various scenarios to identify potential issues and optimize performance. 45 | This is a high-level overview, and there are many details and technical considerations to account for during implementation. It would also be wise to consult existing P2P protocols for ideas and best practices. 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # offgridkom 2 | Off grif communication business card 3 | 4 | 5 | 6 | The project is to develop an electronic board (communicator) capable of sending and receiving messages via WiFi, by Lora or Lorawan radio protocol, and by the ESP-NOW protocol. The mode of communication will vary in several ways. Option 1: Private communication between 2 boards. Option 2: Private communication between 2 boards, but using relays if they are too far apart (Lorawan network with gateways or another communicator serving as a repeater). Option 3: Broadcast communication where all users can hear and participate. A small centralized server will also need to be developed to manage traffic and handle routing. User addresses will be based on ERC-20 addresses or preferably TRC-20 to prepare for future interactions with the blockchain or to allow simple transactions (USDT on TRC-20 for instance) 7 | 8 | 9 | 10 | **Specifications 11 | ** 12 | 13 | Specifications of the "OffGridKom BC" board 14 | The OffGridKom board has the following technical specifications: 15 | Micro-controller ESP32S3 Wroom 1 16 | ST7789 320x172 Color Display 17 | RAKWireless RAK3172 Radio Micro-controller – 868 MHZ* 18 | RainSun 868 MHZ ceramic antenna 19 | T9Word alphanumeric keypad for composing messages 20 | USB-C connection (compatible with external keyboard) 21 | Two micro-switches for ESP32 reset and boot mode 22 | An additional micro-switch for custom function 23 | Board format: Exactly the size of a credit card 24 | Weight: Approximately 20 grams 25 | 26 | 27 | 28 | 29 | The hardware project is proprietary at the moment until we find a way to get a return on all the money invested. 30 | The software is GPL3 31 | 32 | Want to help for this huge project 33 | 34 | TRC-20 USDT: TDbLJ5nTvzbaaSs21Cmf1Lwvhmc5t9W18f 35 | 36 | Polygon Matic: 0xA7Cb711124e1Be5cad35aABB5d8a29b6dfdfc594 37 | 38 | BTC: bc1q6acuv0ghnh743qp8wcz24zkla2h3pa0cxap7zf 39 | 40 | -------------------------------------------------------------------------------- /aeskey_demo2/aeskey_demo2.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | Preferences preferences; 5 | AESLib aesLib; 6 | 7 | void storeAESKey(uint8_t* key, size_t len) { 8 | preferences.begin("aes-settings", false); 9 | preferences.putBytes("aesKey", key, len); 10 | preferences.end(); 11 | } 12 | 13 | bool readStoredAESKey(uint8_t* key, size_t len) { 14 | preferences.begin("aes-settings", true); 15 | size_t keyLen = preferences.getBytes("aesKey", key, len); 16 | preferences.end(); 17 | return keyLen == len; 18 | } 19 | 20 | bool isAESKeyStored() { 21 | uint8_t tempKey[16]; 22 | return readStoredAESKey(tempKey, sizeof(tempKey)); 23 | } 24 | 25 | String encodeMessage(String message) { 26 | uint8_t key[16]; 27 | readStoredAESKey(key, sizeof(key)); 28 | 29 | byte iv[N_BLOCK]; 30 | for (int i = 0; i < N_BLOCK; i++) { 31 | iv[i] = random(0, 256); 32 | } 33 | 34 | byte encryptedMessage[message.length() + N_BLOCK]; 35 | uint16_t encryptedSize = aesLib.encrypt((byte*)message.c_str(), message.length(), encryptedMessage, key, sizeof(key), iv); 36 | 37 | String encrypted = ""; 38 | for (int i = 0; i < N_BLOCK; i++) { 39 | encrypted += String(iv[i], HEX); 40 | } 41 | for (uint16_t i = 0; i < encryptedSize; i++) { 42 | encrypted += String(encryptedMessage[i], HEX); 43 | } 44 | 45 | return encrypted; 46 | } 47 | 48 | void setup() { 49 | Serial.begin(115200); 50 | delay(1000); 51 | 52 | randomSeed(analogRead(0)); 53 | 54 | Serial.println("Looking for stored AES key..."); 55 | if (!isAESKeyStored()) { 56 | Serial.println("No key stored"); 57 | uint8_t newKey[16]; 58 | for (int i = 0; i < 16; i++) { 59 | newKey[i] = random(0, 256); 60 | } 61 | storeAESKey(newKey, sizeof(newKey)); 62 | Serial.println("New AES key generated and stored."); 63 | } else { 64 | Serial.println("Key Found"); 65 | uint8_t storedKey[16]; 66 | readStoredAESKey(storedKey, sizeof(storedKey)); 67 | for (int i = 0; i < sizeof(storedKey); i++) { 68 | Serial.print(storedKey[i], HEX); 69 | Serial.print(" "); 70 | } 71 | Serial.println(); 72 | } 73 | 74 | String plaintext = "Bonjour, ceci est un message"; 75 | Serial.println("Plaintext: " + plaintext); 76 | String encrypted = encodeMessage(plaintext); 77 | Serial.println("Encrypted: " + encrypted); 78 | 79 | // Display IV separately 80 | Serial.print("IV: "); 81 | for (int i = 0; i < N_BLOCK; i++) { 82 | Serial.print(String(encrypted[i], HEX)); 83 | } 84 | Serial.println(); 85 | 86 | } 87 | 88 | void loop() { 89 | // Your regular loop code 90 | } 91 | -------------------------------------------------------------------------------- /demo3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccadic/offgridkom/6d47e3ac04f375781be3d2fc443cb7e00604a6a9/demo3.jpg -------------------------------------------------------------------------------- /demo4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccadic/offgridkom/6d47e3ac04f375781be3d2fc443cb7e00604a6a9/demo4.jpg -------------------------------------------------------------------------------- /espnow-functions/Setup1_st7789_130x320.h: -------------------------------------------------------------------------------- 1 | #ifndef SETUP1_ST7789_130X320_H 2 | #define SETUP1_ST7789_130X320_H 3 | 4 | #include 5 | 6 | #define TFT_WIDTH 172 7 | #define TFT_HEIGHT 320 8 | 9 | #define TFT_MOSI_PIN 35 10 | #define TFT_SCLK_PIN 36 11 | #define TFT_CS_PIN 39 12 | #define TFT_DC_PIN 40 13 | #define TFT_RST_PIN 41 14 | #define TFT_BL_PIN 15 // Backlight control pin 15 | #define TFT_PWR_PIN 16 // Power control pin 16 | 17 | TFT_eSPI tft = TFT_eSPI(); 18 | 19 | #endif // SETUP1_ST7789_130X320_H 20 | -------------------------------------------------------------------------------- /espnow-functions/espnow-functions.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Setup1_st7789_130x320.h" 5 | 6 | uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 7 | 8 | // couleur de fond 9 | uint16_t color = tft.color565(255, 220, 58); 10 | uint16_t colorfond = tft.color565(19, 19, 19); 11 | uint16_t colorgrey = tft.color565(194, 194, 194); 12 | 13 | typedef struct { 14 | char msg[32]; 15 | } Message; 16 | 17 | Message myData; 18 | esp_now_peer_info_t peerInfo; 19 | 20 | void OnDataRecv(const uint8_t *macAddr, const uint8_t *data, int dataLen) { 21 | Message *incoming = (Message*) data; 22 | Serial.print("Received: "); 23 | Serial.println(incoming->msg); 24 | tft.setTextColor(colorgrey); 25 | tft.setTextDatum(TL_DATUM); 26 | tft.setTextSize(1); 27 | tft.drawString(String("Received: ") + incoming->msg, 30, 120); 28 | } 29 | 30 | void setup() { 31 | // Init Serial Monitor 32 | Serial.begin(115200); 33 | 34 | // Set device as a Wi-Fi Station 35 | WiFi.mode(WIFI_STA); 36 | 37 | pinMode(TFT_PWR_PIN, OUTPUT); 38 | pinMode(TFT_BL_PIN, OUTPUT); 39 | 40 | digitalWrite(TFT_PWR_PIN, HIGH); // Turn on the display power 41 | digitalWrite(TFT_BL_PIN, HIGH); // Turn on the backlight 42 | 43 | tft.begin(); 44 | tft.setRotation(3); // Set the screen rotation 45 | 46 | tft.setSwapBytes(true); // Swap the byte order for pushImage() 47 | tft.fillScreen(TFT_BLACK); 48 | 49 | // Get MAC Address of the device and print it 50 | String mac = WiFi.macAddress(); 51 | tft.setTextColor(colorgrey); 52 | tft.setTextDatum(TL_DATUM); 53 | tft.setTextSize(1); 54 | tft.drawString("MAC: " + mac, 30, 25); 55 | 56 | Serial.println("MAC: " + mac); 57 | 58 | // Init ESP-NOW 59 | if (esp_now_init() != ESP_OK) { 60 | Serial.println("Error initializing ESP-NOW"); 61 | tft.setTextColor(colorgrey); 62 | tft.setTextDatum(TL_DATUM); 63 | tft.setTextSize(1); 64 | tft.drawString("Error initializing ESP-NOW", 30, 50); 65 | return; 66 | } 67 | 68 | // Register for receive callback 69 | esp_now_register_recv_cb(OnDataRecv); 70 | 71 | // Register peer 72 | memcpy(peerInfo.peer_addr, broadcastAddress, 6); 73 | peerInfo.channel = 0; 74 | peerInfo.encrypt = false; 75 | 76 | // Add peer 77 | if (esp_now_add_peer(&peerInfo) != ESP_OK) { 78 | Serial.println("Failed to add peer"); 79 | tft.setTextColor(colorgrey); 80 | tft.setTextDatum(TL_DATUM); 81 | tft.setTextSize(1); 82 | tft.drawString("Failed to add peer", 30, 75); 83 | return; 84 | } 85 | 86 | Serial.println("Setup complete"); 87 | tft.drawString("Requester Setup complete", 30, 100); 88 | } 89 | 90 | void loop() { 91 | strcpy(myData.msg, "Who is Device X?"); 92 | esp_now_send(broadcastAddress, (uint8_t*)&myData, sizeof(myData)); 93 | delay(2000); 94 | } 95 | -------------------------------------------------------------------------------- /espnow-receiver-code/Setup1_st7789_130x320.h: -------------------------------------------------------------------------------- 1 | #ifndef SETUP1_ST7789_130X320_H 2 | #define SETUP1_ST7789_130X320_H 3 | 4 | #include 5 | 6 | #define TFT_WIDTH 172 7 | #define TFT_HEIGHT 320 8 | 9 | #define TFT_MOSI_PIN 35 10 | #define TFT_SCLK_PIN 36 11 | #define TFT_CS_PIN 39 12 | #define TFT_DC_PIN 40 13 | #define TFT_RST_PIN 41 14 | #define TFT_BL_PIN 15 // Backlight control pin 15 | #define TFT_PWR_PIN 16 // Power control pin 16 | 17 | TFT_eSPI tft = TFT_eSPI(); 18 | 19 | #endif // SETUP1_ST7789_130X320_H 20 | -------------------------------------------------------------------------------- /espnow-receiver-code/espnow-receiver-code.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Setup1_st7789_130x320.h" 5 | 6 | uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 7 | 8 | uint16_t color = tft.color565(255, 220, 58); 9 | uint16_t colorfond = tft.color565(19, 19, 19); 10 | uint16_t colorgrey = tft.color565(194, 194, 194); 11 | 12 | typedef struct { 13 | char msg[32]; 14 | } Message; 15 | 16 | Message responseMsg; 17 | 18 | String macToString(const uint8_t* mac) { 19 | char buf[20]; 20 | snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 21 | return String(buf); 22 | } 23 | 24 | void OnDataRecv(const uint8_t *macAddr, const uint8_t *data, int dataLen) { 25 | Message *incoming = (Message*) data; 26 | 27 | String senderMac = macToString(macAddr); 28 | Serial.println("Received from: " + senderMac); 29 | tft.setTextColor(colorgrey); 30 | tft.setTextDatum(TL_DATUM); 31 | tft.setTextSize(1); 32 | tft.drawString("From: " + senderMac, 30, 120); 33 | 34 | if (strcmp(incoming->msg, "Who is Device X?") == 0) { 35 | strcpy(responseMsg.msg, "I am Device X"); 36 | tft.setTextColor(colorgrey); 37 | tft.setTextDatum(TL_DATUM); 38 | tft.setTextSize(1); 39 | tft.drawString("Replying: I am Device X", 30, 100); 40 | 41 | // Envoi en broadcast 42 | esp_err_t result = esp_now_send(broadcastAddress, (uint8_t*)&responseMsg, sizeof(responseMsg)); 43 | 44 | if (result != ESP_OK) { 45 | Serial.println("Error sending the response. Error code: " + String(result)); 46 | tft.setTextColor(colorgrey); 47 | tft.setTextDatum(TL_DATUM); 48 | tft.setTextSize(1); 49 | tft.drawString("Error sending the response", 30, 25); 50 | } 51 | } 52 | } 53 | void setup() { 54 | Serial.begin(115200); 55 | WiFi.mode(WIFI_STA); 56 | 57 | pinMode(TFT_PWR_PIN, OUTPUT); 58 | pinMode(TFT_BL_PIN, OUTPUT); 59 | digitalWrite(TFT_PWR_PIN, HIGH); 60 | digitalWrite(TFT_BL_PIN, HIGH); 61 | 62 | tft.begin(); 63 | tft.setRotation(3); 64 | tft.setSwapBytes(true); 65 | tft.fillScreen(TFT_BLACK); 66 | 67 | if (esp_now_init() != ESP_OK) { 68 | Serial.println("Error initializing ESP-NOW"); 69 | tft.setTextColor(colorgrey); 70 | tft.setTextDatum(TL_DATUM); 71 | tft.setTextSize(1); 72 | tft.drawString("Error initializing ESP-NOW", 30, 40); 73 | return; 74 | } 75 | 76 | esp_now_register_recv_cb(OnDataRecv); 77 | 78 | esp_now_peer_info_t peerInfo; 79 | memcpy(peerInfo.peer_addr, broadcastAddress, 6); 80 | peerInfo.channel = 0; 81 | peerInfo.encrypt = false; 82 | //peerInfo.ifidx = ESP_IF_WIFI_STA; 83 | peerInfo.ifidx = WIFI_IF_STA; 84 | 85 | 86 | if (esp_now_add_peer(&peerInfo) != ESP_OK) { 87 | Serial.println("Failed to add peer"); 88 | tft.setTextColor(colorgrey); 89 | tft.setTextDatum(TL_DATUM); 90 | tft.setTextSize(1); 91 | tft.drawString("Failed to add peer", 30, 55); 92 | return; 93 | } 94 | 95 | Serial.println("Receiver set up"); 96 | tft.setTextColor(colorgrey); 97 | tft.setTextDatum(TL_DATUM); 98 | tft.setTextSize(1); 99 | tft.drawString("Receiver set up", 30, 70); 100 | } 101 | 102 | void loop() { 103 | delay(1000); 104 | } 105 | -------------------------------------------------------------------------------- /k9code/Setup1_st7789_130x320.h: -------------------------------------------------------------------------------- 1 | #ifndef SETUP1_ST7789_130X320_H 2 | #define SETUP1_ST7789_130X320_H 3 | 4 | #include 5 | 6 | #define TFT_WIDTH 172 7 | #define TFT_HEIGHT 320 8 | 9 | #define TFT_MOSI_PIN 35 10 | #define TFT_SCLK_PIN 36 11 | #define TFT_CS_PIN 39 12 | #define TFT_DC_PIN 40 13 | #define TFT_RST_PIN 41 14 | #define TFT_BL_PIN 15 // Backlight control pin 15 | #define TFT_PWR_PIN 16 // Power control pin 16 | 17 | TFT_eSPI tft = TFT_eSPI(); 18 | 19 | #endif // SETUP1_ST7789_130X320_H 20 | -------------------------------------------------------------------------------- /k9code/k9-1.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccadic/offgridkom/6d47e3ac04f375781be3d2fc443cb7e00604a6a9/k9code/k9-1.docx -------------------------------------------------------------------------------- /k9code/k9code.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Setup1_st7789_130x320.h" 3 | #include 4 | #include "offgrid_intro.h" 5 | 6 | // Paramètres WiFi 7 | const char* ssid = "RadissonBlu-Guest"; 8 | 9 | // couleur de fond pour TFT espi 10 | uint16_t color = tft.color565(255, 220, 58); 11 | uint16_t colorfond = tft.color565(19, 19, 19); 12 | uint16_t colorgrey = tft.color565(194, 194, 194); 13 | 14 | const char* keys[] = { 15 | "1.,?!@*#", "2ABC", "3DEF", "4GHI", "5JKL", "6MNO", "7PQRS", "8TUV", "9WXYZ", "*SHIFT", "0", "#" 16 | }; 17 | 18 | const int gpioKeys[] = { 19 | 7, 17, 18, 8, 46, 9, 10, 11, 12, 13, 21, 47 20 | }; 21 | 22 | bool isShift = false; 23 | 24 | String edittext(String zetext) { 25 | int lastKeyIndex = -1; 26 | int countKeyPress = 0; 27 | unsigned long lastKeyPressTime = 0; 28 | const unsigned long timeout = 1000; // 1 second to switch character or confirm 29 | 30 | while (true) { 31 | for (int i = 0; i < 12; i++) { 32 | if (digitalRead(gpioKeys[i]) == HIGH) { // Assuming pull-up configuration, button press is LOW 33 | if (i == 9) { // BackSpace 34 | if (zetext.length() > 0) { 35 | zetext.remove(zetext.length() - 1); 36 | } 37 | } else if (i == 11) { // ENTER key 38 | return zetext; 39 | } else if (i == 10) { // "0" key 40 | if (lastKeyIndex == i && (millis() - lastKeyPressTime) < timeout) { 41 | countKeyPress++; 42 | if (countKeyPress == 1) { 43 | zetext += "0"; 44 | } else if (countKeyPress == 2) { 45 | zetext += " "; 46 | countKeyPress = 0; // Reset it for next cycle. 47 | } 48 | } else { 49 | countKeyPress = 0; 50 | zetext += "0"; // Add zero if any other key was pressed before. 51 | } 52 | lastKeyIndex = i; 53 | lastKeyPressTime = millis(); 54 | } else { 55 | if (lastKeyIndex == i && (millis() - lastKeyPressTime) < timeout) { 56 | countKeyPress++; 57 | } else { 58 | countKeyPress = 0; 59 | } 60 | lastKeyIndex = i; 61 | lastKeyPressTime = millis(); 62 | 63 | int charIndex = countKeyPress % strlen(keys[i]); 64 | char character = keys[i][charIndex]; 65 | if (isShift && character >= 'a' && character <= 'z') { 66 | character -= 32; // Convert to uppercase 67 | } 68 | zetext += character; 69 | 70 | if (countKeyPress > 0 && zetext.length() > 1) { 71 | zetext.remove(zetext.length() - 2, 1); // Remove the previous character 72 | } 73 | } 74 | 75 | // Display the updated zetext 76 | tft.fillScreen(TFT_BLACK); 77 | tft.pushImage(0, 30, 320, 172, offgrid_intro); 78 | tft.setCursor(10, 100); 79 | tft.setTextColor(color); 80 | tft.setTextSize(2); 81 | tft.print(zetext); 82 | 83 | // Delay to manage button debounce 84 | delay(200); 85 | } 86 | } 87 | } 88 | } 89 | 90 | void setup() { 91 | pinMode(TFT_PWR_PIN, OUTPUT); 92 | pinMode(TFT_BL_PIN, OUTPUT); 93 | digitalWrite(TFT_PWR_PIN, HIGH); 94 | digitalWrite(TFT_BL_PIN, HIGH); 95 | 96 | tft.begin(); 97 | tft.setRotation(3); 98 | 99 | tft.setSwapBytes(true); 100 | tft.fillScreen(TFT_BLACK); 101 | tft.pushImage(0, 30, 320, 172, offgrid_intro); 102 | 103 | for (int i = 0; i < 12; i++) { 104 | pinMode(gpioKeys[i], INPUT_PULLUP); 105 | } 106 | 107 | WiFi.begin(ssid); 108 | while (WiFi.status() != WL_CONNECTED) { 109 | delay(1000); 110 | Serial.println("Connexion au WiFi..."); 111 | } 112 | } 113 | 114 | void loop() { 115 | // For demonstration purposes: 116 | String result = edittext(""); 117 | tft.setCursor(10, 130); 118 | tft.setTextColor(colorgrey); 119 | tft.setTextSize(2); 120 | tft.print(result); 121 | delay(5000); // Display the result for 5 seconds before clearing 122 | } 123 | 124 | 125 | -------------------------------------------------------------------------------- /sulfuroid_A_close_portrait_of_a_modern_dark_purple_hair_glamour_3bb2f303-f06c-4190-96b3-a40f14463b5a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccadic/offgridkom/6d47e3ac04f375781be3d2fc443cb7e00604a6a9/sulfuroid_A_close_portrait_of_a_modern_dark_purple_hair_glamour_3bb2f303-f06c-4190-96b3-a40f14463b5a.png --------------------------------------------------------------------------------