Added T-Deck documentation, parts list, gps install guide, etc. Added MQTT connection script (still working on this)
This commit is contained in:
parent
ddb5a4b323
commit
f92093d889
12
FIRMWARE.md
12
FIRMWARE.md
@ -1,32 +1,34 @@
|
|||||||
# Meshtastic Firmware Hacks
|
# Meshtastic Firmware Hacks
|
||||||
|
|
||||||
### Custom Boot Logo & Message
|
## Prerequisite
|
||||||
- Download & install [PlatformIO](https://platformio.org/platformio-ide)
|
- Download & install [PlatformIO](https://platformio.org/platformio-ide)
|
||||||
|
|
||||||
- `git clone https://github.com/meshtastic/firmware.git`
|
- `git clone https://github.com/meshtastic/firmware.git`
|
||||||
|
|
||||||
- `cd firmware && git submodule update --init`
|
- `cd firmware && git submodule update --init`
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
###### Custom Boot Logo
|
||||||
- Use [XMB Viewer](https://windows87.github.io/xbm-viewer-converter/) to convert an image to XMB
|
- Use [XMB Viewer](https://windows87.github.io/xbm-viewer-converter/) to convert an image to XMB
|
||||||
|
|
||||||
- The data from this goes in `firmware/src/graphics/img/icon.xbm`
|
- The data from this goes in `firmware/src/graphics/img/icon.xbm`
|
||||||
|
|
||||||
### Custom boot message
|
###### Custom boot message
|
||||||
- Navigate to `firmware/src/graphics/Screen.cpp`
|
- Navigate to `firmware/src/graphics/Screen.cpp`
|
||||||
|
|
||||||
- Find & replace `const char *title = "meshtastic.org";` with your custom message.
|
- Find & replace `const char *title = "meshtastic.org";` with your custom message.
|
||||||
|
|
||||||
### Custom screen color
|
###### Custom screen color
|
||||||
- Navigate to `src/graphics/TFTDisplay.cpp`
|
- Navigate to `src/graphics/TFTDisplay.cpp`
|
||||||
|
|
||||||
- Find & replace `#define TFT_MESH COLOR565(0x67, 0xEA, 0x94)` with your custom color.
|
- Find & replace `#define TFT_MESH COLOR565(0x67, 0xEA, 0x94)` with your custom color.
|
||||||
|
|
||||||
### Custom alert sound (for T-Deck & devices with a buzzer)
|
###### Custom alert sound (for T-Deck & devices with a buzzer)
|
||||||
- From the mobile app, click the 3 dots on the top right, and select `Radio configuration`
|
- From the mobile app, click the 3 dots on the top right, and select `Radio configuration`
|
||||||
- Under `Module configuration`, select `External Notification`
|
- Under `Module configuration`, select `External Notification`
|
||||||
- Scroll down & you will see a `Ringtone` option that takes [RTTTL](https://en.wikipedia.org/wiki/Ring_Tone_Text_Transfer_Language) formatted tones.
|
- Scroll down & you will see a `Ringtone` option that takes [RTTTL](https://en.wikipedia.org/wiki/Ring_Tone_Text_Transfer_Language) formatted tones.
|
||||||
|
|
||||||
As far as I know, at the time of writing this, the onyl way to change the Ringtone is from the App...
|
As far as I know, at the time of writing this, the only way to change the Ringtone is from the App. While this is not a "firmware" related thing, I included it in this file because it was difficult to find this setting...
|
||||||
|
|
||||||
## Compile & flash firmware
|
## Compile & flash firmware
|
||||||
- Select `PlatformIO: Pick Project Environment` & select your board.
|
- Select `PlatformIO: Pick Project Environment` & select your board.
|
||||||
|
23
T-DECK.md
Normal file
23
T-DECK.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# LilyGo T-Deck Notes
|
||||||
|
|
||||||
|
## Parts
|
||||||
|
- [T-Deck](https://www.lilygo.cc/products/t-deck)
|
||||||
|
- [Case](https://www.printables.com/model/741124-lilygo-t-deck-case) *(You can 3D print it yourself, or follow the Etsy link on here to buy one)*
|
||||||
|
- [Antenna](https://www.amazon.com/dp/B086ZG5WBR)
|
||||||
|
- [GPS](https://www.amazon.com/dp/B09LQDG1HY) *(There may be a better 15mm option for the case above..)*
|
||||||
|
- [Battery](https://www.amazon.com/dp/B0BG82T39Y) *(The battery you get depends on the size of the case you order, contact me if you need help)*
|
||||||
|
|
||||||
|
**WARNING:** Do not power on the device until the antenna is plugged in! Even to flash the firmware, or for testing, make sure your antenna is plugged in or you can fry the radio!
|
||||||
|
|
||||||
|
## GPS Installation
|
||||||
|
The T-Deck has a grove connector for the GPS. Personally, I do not use a grove connector for mine, I removed the Grove input and soldered directly to the board.
|
||||||
|
|
||||||
|
**WARNING**: Be careful taking off the grove! Snip the front points, and then use a soldering iron to loosen the metal on the 4 contact back points. You can VERY easily pull the solder pads right off if you just try to rip the grove connector off without loosening the solder points. If you pull off a solder pad, you're pretty much boned on having a GPS module.
|
||||||
|
|
||||||
|
You will see VCC, GND, RX & TX points on both the T-Deck & the GPS. Solder wires to match these points, but switch RX & TX. So do VCC to VCC, GND to GND, and then ensure that RX is soldered to TX, and TX is soldered to RX. It's confusing, I know, but that's China based hardware for you...
|
||||||
|
|
||||||
|
## Flashing
|
||||||
|
Simply plug in the T-Deck via USB and connect to a computer, then visit the [Meshtastic Web Flasher](https://flasher.meshtastic.org) and select your hardware & firmware version. Your device should show up as a serial device on /dev/ttyUSB0 or /dev/ttyAMC0. If you do not see your device, try adding your user to the dialout group. See [SETUP.md](./SETUP.md) for information on how to setup the device once it is flashed with Meshtastic.
|
||||||
|
|
||||||
|
## Issues
|
||||||
|
- Turn off WiFi completely if you plan to use this on-the-go. The device has an ESP32 chip which will always preffer WiFi over Bluetooth, so if you leave the house with this thign, it will constantly keep trying to connect to your WiFi & really degrade the performance of the board.
|
185
meshmqtt.py
185
meshmqtt.py
@ -1,88 +1,151 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# Meshtastic MQTT Interface - Developed by Acidvegas in Python (https://git.acid.vegas/meshtastic)
|
# Meshtastic MQTT Interface - Developed by acidvegas in Python (https://acid.vegas/meshtastic)
|
||||||
|
|
||||||
|
import argparse
|
||||||
import base64
|
import base64
|
||||||
import random
|
import logging
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError('cryptography library not found (pip install cryptography)')
|
raise SystemExit('missing the cryptography module (pip install cryptography)')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from meshtastic import mesh_pb2, mqtt_pb2, portnums_pb2, telemetry_pb2
|
from meshtastic import mesh_pb2, mqtt_pb2, portnums_pb2, telemetry_pb2
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError('meshtastic library not found (pip install meshtastic)')
|
raise SystemExit('missing the meshtastic module (pip install meshtastic)')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError('paho-mqtt library not found (pip install paho-mqtt)')
|
raise SystemExit('missing the paho-mqtt module (pip install paho-mqtt)')
|
||||||
|
|
||||||
|
|
||||||
# MQTT Configuration
|
def process_message(message_packet, text_payload, is_encrypted):
|
||||||
MQTT_BROKER = 'localhost'
|
|
||||||
MQTT_PORT = 1883
|
text = {
|
||||||
MQTT_USERNAME = 'username'
|
'message': text_payload,
|
||||||
MQTT_PASSWORD = 'password'
|
'from': getattr(message_packet, 'from'),
|
||||||
MQTT_ROOT_TOPIC = 'msh/US/2/c/'
|
'id': getattr(message_packet, 'id'),
|
||||||
CHANNEL_KEY = 'channel_key'
|
'to': getattr(message_packet, 'to')
|
||||||
|
}
|
||||||
|
print(text)
|
||||||
|
|
||||||
|
|
||||||
|
def decode_encrypted(message_packet):
|
||||||
|
'''
|
||||||
|
Decrypt an encrypted message packet.
|
||||||
|
|
||||||
|
:param message_packet: The message packet to decrypt'''
|
||||||
|
try:
|
||||||
|
key_bytes = base64.b64decode(key.encode('ascii'))
|
||||||
|
|
||||||
|
nonce_packet_id = getattr(message_packet, 'id').to_bytes(8, 'little')
|
||||||
|
nonce_from_node = getattr(message_packet, 'from').to_bytes(8, 'little')
|
||||||
|
nonce = nonce_packet_id + nonce_from_node
|
||||||
|
|
||||||
|
cipher = Cipher(algorithms.AES(key_bytes), modes.CTR(nonce), backend=default_backend())
|
||||||
|
decryptor = cipher.decryptor()
|
||||||
|
decrypted_bytes = decryptor.update(getattr(message_packet, 'encrypted')) + decryptor.finalize()
|
||||||
|
|
||||||
|
data = mesh_pb2.Data()
|
||||||
|
data.ParseFromString(decrypted_bytes)
|
||||||
|
message_packet.decoded.CopyFrom(data)
|
||||||
|
|
||||||
|
if message_packet.decoded.portnum == portnums_pb2.TEXT_MESSAGE_APP:
|
||||||
|
text_payload = message_packet.decoded.payload.decode('utf-8')
|
||||||
|
is_encrypted = True
|
||||||
|
process_message(message_packet, text_payload, is_encrypted)
|
||||||
|
print(f'{text_payload}')
|
||||||
|
|
||||||
|
|
||||||
|
elif message_packet.decoded.portnum == portnums_pb2.NODEINFO_APP:
|
||||||
|
info = mesh_pb2.User()
|
||||||
|
info.ParseFromString(message_packet.decoded.payload)
|
||||||
|
print(info)
|
||||||
|
|
||||||
|
elif message_packet.decoded.portnum == portnums_pb2.POSITION_APP:
|
||||||
|
pos = mesh_pb2.Position()
|
||||||
|
pos.ParseFromString(message_packet.decoded.payload)
|
||||||
|
print(pos)
|
||||||
|
|
||||||
|
elif message_packet.decoded.portnum == portnums_pb2.TELEMETRY_APP:
|
||||||
|
env = telemetry_pb2.Telemetry()
|
||||||
|
env.ParseFromString(message_packet.decoded.payload)
|
||||||
|
print(env)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f'Failed to decrypt message: {str(e)}')
|
||||||
|
|
||||||
|
|
||||||
def on_connect(client, userdata, flags, rc, properties):
|
def on_connect(client, userdata, flags, rc, properties):
|
||||||
'''
|
'''
|
||||||
Callback for when the client receives a CONNACK response from the server.
|
Callback for when the client receives a CONNACK response from the server.
|
||||||
|
|
||||||
:param client: The client instance for this callback
|
:param client: The client instance for this callback
|
||||||
:param userdata: The private user data as set in Client() or user_data_set()
|
:param userdata: The private user data as set in Client() or user_data_set()
|
||||||
:param flags: Response flags sent by the broker
|
:param flags: Response flags sent by the broker
|
||||||
:param rc: The connection result
|
:param rc: The connection result
|
||||||
:param properties: The properties returned by the broker
|
:param properties: The properties returned by the broker
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
print('Connected to MQTT broker')
|
print('Connected to MQTT broker')
|
||||||
|
else:
|
||||||
else:
|
logging.error(f'Failed to connect to MQTT broker: {rc}')
|
||||||
print(f"Failed to connect to MQTT broker with result code {str(rc)}")
|
|
||||||
|
|
||||||
|
|
||||||
def on_message(client, userdata, msg):
|
def on_message(client, userdata, msg):
|
||||||
'''
|
'''
|
||||||
Callback for when a PUBLISH message is received from the server.
|
Callback for when a message is received from the server.
|
||||||
|
|
||||||
:param client: The client instance for this callback
|
:param client: The client instance for this callback
|
||||||
:param userdata: The private user data as set in Client() or user_data_set()
|
:param userdata: The private user data as set in Client() or user_data_set()
|
||||||
:param msg: An instance of MQTTMessage. This is a class with members topic, payload, qos, retain.
|
:param msg: An instance of MQTTMessage. This is a
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
service_envelope = mqtt_pb2.ServiceEnvelope()
|
||||||
|
|
||||||
service_envelope = mqtt_pb2.ServiceEnvelope()
|
try:
|
||||||
|
service_envelope.ParseFromString(msg.payload)
|
||||||
|
# print(service_envelope)
|
||||||
|
message_packet = service_envelope.packet
|
||||||
|
# print(message_packet)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f'Failed to parse message: {str(e)}')
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
if message_packet.HasField('encrypted') and not message_packet.HasField('decoded'):
|
||||||
service_envelope.ParseFromString(msg.payload)
|
decode_encrypted(message_packet)
|
||||||
print(service_envelope)
|
|
||||||
|
|
||||||
message_packet = service_envelope.packet
|
|
||||||
print(message_packet)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f'error on message: {e}')
|
|
||||||
|
|
||||||
else:
|
|
||||||
if message_packet.HasField('encrypted') and not message_packet.HasField('decoded'): # Do we need to check for both?
|
|
||||||
pass # Need to finish this
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
parser = argparse.ArgumentParser(description='Mesh MQTT')
|
||||||
client.on_connect = on_connect
|
parser.add_argument('--broker', default='mqtt.meshtastic.org', help='MQTT broker address')
|
||||||
client.username_pw_set(username=MQTT_USERNAME, password=MQTT_PASSWORD)
|
parser.add_argument('--port', default=1883, type=int, help='MQTT broker port')
|
||||||
client.connect(MQTT_BROKER, MQTT_PORT, 60)
|
parser.add_argument('--root', default='msh/US/2/c', help='Root topic')
|
||||||
client.on_message = on_message
|
parser.add_argument('--tls', action='store_true', help='Enable TLS/SSL')
|
||||||
client.subscribe(MQTT_ROOT_TOPIC, 0) # This is the topic that the Meshtastic device is publishing to
|
parser.add_argument('--username', default='meshdev', help='MQTT username')
|
||||||
|
parser.add_argument('--password', default='large4cats', help='MQTT password')
|
||||||
|
parser.add_argument('--key', default='AQ==', help='Encryption key')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Keep-alive loop
|
# Ensure the key is padded and formatted correctly
|
||||||
while client.loop() == 0:
|
padded_key = args.key.ljust(len(args.key) + ((4 - (len(args.key) % 4)) % 4), '=')
|
||||||
pass
|
replaced_key = padded_key.replace('-', '+').replace('_', '/')
|
||||||
|
key = replaced_key
|
||||||
|
|
||||||
|
broadcast_id = 4294967295
|
||||||
|
|
||||||
|
# client = mqtt.Client(client_id='', clean_session=True, userdata=None)
|
||||||
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
||||||
|
client.on_connect = on_connect
|
||||||
|
client.username_pw_set(username=args.username, password=args.password)
|
||||||
|
client.connect(args.broker, args.port, 60)
|
||||||
|
client.on_message = on_message
|
||||||
|
client.subscribe(args.root, 0)
|
||||||
|
|
||||||
|
while client.loop() == 0:
|
||||||
|
pass
|
||||||
|
Loading…
Reference in New Issue
Block a user