meshtastic

- Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.acid.vegas/-c.git
Log | Files | Refs | Archive | README | LICENSE

commit e0754f1f0258008961720a3bacefd582555c1fcf
parent 3fabecb8aac1d4ba75fb5a649f13535d3fe0bbe8
Author: acidvegas <acid.vegas@acid.vegas>
Date: Mon, 29 Apr 2024 14:15:38 -0400

Added some firmware hacking documentation for customization, white-space cleanup, etc

Diffstat:
AFIRMWARE_HACKS.md | 40++++++++++++++++++++++++++++++++++++++++
MREADME.md | 2++
Mmeshirc.py | 24++++++++++++------------
Mmeshtastic_serial.py | 28+++++++++++-----------------

4 files changed, 65 insertions(+), 29 deletions(-)

diff --git a/FIRMWARE_HACKS.md b/FIRMWARE_HACKS.md
@@ -0,0 +1,39 @@
+# Meshtastic Firmware Hacks
+
+### Custom Boot Logo & Message
+- Download & install [PlatformIO](https://platformio.org/platformio-ide)
+
+- `git clone https://github.com/meshtastic/firmware.git`
+
+- `cd firmware && git submodule update --init`
+
+- 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`
+
+### Custom boot message
+- Navigate to `firmware/src/graphics/Screen.cpp`
+
+- Find & replace `const char *title = "meshtastic.org";` with your custom message.
+
+### Custom screen color
+ - Navigate to `src/graphics/TFTDisplay.cpp`
+
+ - Find & replace `#define TFT_MESH COLOR565(0x67, 0xEA, 0x94)` with your custom color.
+
+ ### 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`
+ - 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.
+
+As far as I know, at the time of writing this, the onyl way to change the Ringtone is from the App...
+
+
+ ## Compile & flash firmware
+ - Select `PlatformIO: Pick Project Environment` & select your board.
+ - Run `PLatformIO: Build` to compile the firmware.
+ - Place device in DFU mode & plug in to the computer
+ - Do `PlatformIO: Upload` to send the firmware to the device
+ - Press the RESET button or reboot your device.
+
+ See [here](https://meshtastic.org/docs/development/firmware/build/) for more information building & flashing custom firmware.
+\ No newline at end of file
diff --git a/README.md b/README.md
@@ -10,6 +10,8 @@ The goal here is to create simple & clean modules to interface with the hardware
 
 The hardware I am experimenting with: [Lilygo T-Deck](https://www.lilygo.cc/products/t-deck), [Lilygo T-Beam](https://www.lilygo.cc/products/t-beam-v1-1-esp32-lora-module), [Heltec Lora 32 v3](https://heltec.org/project/wifi-lora-32-v3/), and [RAK Wireless 4631](https://store.rakwireless.com/products/wisblock-core-modules?variant=42440631419078)
 
+## Notes to self & developers
+- The node id formula is: f'!{hex(node_num)[2:]}'
 
 ## Hardware & Software related Issues
 - T-Deck must have Wifi turned off when going mobile. Upon leaving my house with WiFi still enabled, the UI & connection was EXTREMELY laggy & poor. Couldn't even type well...
diff --git a/meshirc.py b/meshirc.py
@@ -7,6 +7,7 @@ import logging
 import ssl
 import time
 
+# EF576MkXA3aEURbCfNn6p0FfZdua4I
 
 # Formatting Control Characters / Color Codes
 bold        = '\x02'
@@ -44,7 +45,7 @@ def color(msg: str, foreground: str, background: str = None) -> str:
 	:param foreground: The foreground color to use.
 	:param background: The background color to use.
 	'''
- 
+
 	return f'\x03{foreground},{background}{msg}{reset}' if background else f'\x03{foreground}{msg}{reset}'
 
 
@@ -63,7 +64,7 @@ class Bot():
 		:param chan: The channel to send the ACTION to.
 		:param msg: The message to send to the channel.
 		'''
-  
+
 		await self.sendmsg(chan, f'\x01ACTION {msg}\x01')
 
 
@@ -73,7 +74,7 @@ class Bot():
 
 		:param data: The raw data to send to the IRC server. (512 bytes max including crlf)
 		'''
-  
+
 		await self.writer.write(data[:510].encode('utf-8') + b'\r\n')
 
 
@@ -84,13 +85,13 @@ class Bot():
 		:param target: The target to send the PRIVMSG to. (channel or user)
 		:param msg: The message to send to the target.
 		'''
-  
+
 		await self.raw(f'PRIVMSG {target} :{msg}')
 
 
 	async def connect(self):
 		'''Connect to the IRC server.'''
-  
+
 		while True:
 			try:
 				options = {
@@ -124,7 +125,7 @@ class Bot():
 
 		:param data: The data received from the IRC server.
 		'''
-  
+
 		parts  = data.split()
 
 		ident  = parts[0][1:]
@@ -146,7 +147,7 @@ class Bot():
 						if len(message) > 255:
 							await self.sendmsg(target, color('Message exceeds 255 bytes nerd!', red))
 						# TODO: Send a meshtastic message (We have to ensure our outbounds from IRC don't loop back into IRC)
-						
+
 					self.last = time.time() # Update the last command time if it starts with ! character to prevent command flooding
 
 
@@ -156,9 +157,9 @@ class Bot():
 
 		:param data: The data received from the IRC server.
 		'''
-  
+
 		logging.info(data)
-  
+
 		try:
 			parts = data.split()
 
@@ -207,7 +208,7 @@ if __name__ == '__main__':
 	parser.add_argument('--ssl', action='store_true', help='Use SSL for the connection.')
 	parser.add_argument('--key',  default='', help='The key (password) for the IRC channel, if required.')
 	args = parser.parse_args()
- 
+
 	if not args.channel.startswith('#'):
 		channel = '#' + args.channel
 
@@ -220,4 +221,4 @@ if __name__ == '__main__':
 
 	bot = Bot()
 
-	asyncio.run(bot.connect())
-\ No newline at end of file
+	asyncio.run(bot.connect())
diff --git a/meshtastic_serial.py b/meshtastic_serial.py
@@ -17,24 +17,18 @@ except ImportError:
 try:
 	from pubsub import pub
 except ImportError:
-	raise ImportError('pubsub library not found (pip install pypubsub)') # Confirm this Pypi package name...
+	raise ImportError('pubsub library not found (pip install pypubsub)')
 
 
 # Initialize logging
 logging.basicConfig(level=logging.INFO, format='%(asctime)s | %(levelname)9s | %(funcName)s | %(message)s', datefmt='%Y-%m-%d %I:%M:%S')
 
 
-def now():
-	'''Returns the current date and time in a formatted string'''
-
-	return time.strftime('%Y-%m-%d %H:%M:%S')
-
-
 class MeshtasticClient(object):
 	def __init__(self):
-		self.interface = None # We will define the interface in the connect() function
-		self.me        = {}   # We will populate this with the event_connect() callback
-		self.nodes     = {}   # Nodes will populate with the event_node() callback
+		self.interface = None
+		self.me        = {} 
+		self.nodes     = {}
 
 
 	def connect(self, option: str, value: str):
@@ -71,7 +65,7 @@ class MeshtasticClient(object):
 				break
 
 
-	def send(self, message: str):
+	def sendmsg(self, message: str, destination: int, channelIndex: int = 0):
 		'''
 		Send a message to the Meshtastic interface
 
@@ -82,7 +76,7 @@ class MeshtasticClient(object):
 			logging.warning('Message exceeds 255 characters')
 			message = message[:255]
 
-		self.interface.sendText(message)
+		self.interface.sendText(message, destination, wantAck=True, channelIndex=channelIndex) # Do we need wantAck?
 
 		logging.info(f'Sent broadcast message: {message}')
 
@@ -121,7 +115,7 @@ class MeshtasticClient(object):
 		:param interface: Meshtastic interface
 		'''
 
-		logging.info(f'Data update: {data}')
+		logging.info(f'Data update: {packet}')
 
 
 	def event_disconnect(self, interface, topic=pub.AUTO_TOPIC):
@@ -149,7 +143,7 @@ class MeshtasticClient(object):
 
 		self.nodes[node['num']] = node
 
-		logging.info(f'Node found: {node["user"]["id"]} - {node["user"]["shortName"].ljust(4)} - {node["user"]["longName"]}')
+		logging.info(f'Node recieved: {node["user"]["id"]} - {node["user"]["shortName"].ljust(4)} - {node["user"]["longName"]}')
 
 
 	def event_position(self, packet: dict, interface):
@@ -161,7 +155,7 @@ class MeshtasticClient(object):
 		'''
 
 		sender    = packet['from']
-		msg       = packet['decoded']['payload'].hex()
+		msg       = packet['decoded']['payload'].hex() # What exactly is contained in this payload?
 		id        = self.nodes[sender]['user']['id']       if sender in self.nodes else '!unk   '
 		name      = self.nodes[sender]['user']['longName'] if sender in self.nodes else 'UNK'
 		longitude = packet['decoded']['position']['longitudeI'] / 1e7
@@ -170,7 +164,7 @@ class MeshtasticClient(object):
 		snr	      = packet['rxSnr']
 		rssi	  = packet['rxRssi']
 
-		logging.info(f'{id} - {name}: {longitude}, {latitude}, {altitude}m (SNR: {snr}, RSSI: {rssi}) - {msg}')
+		logging.info(f'Position recieved: {id} - {name}: {longitude}, {latitude}, {altitude}m (SNR: {snr}, RSSI: {rssi}) - {msg}')
 
 
 	def event_text(self, packet: dict, interface):
@@ -187,7 +181,7 @@ class MeshtasticClient(object):
 		name   = self.nodes[sender]['user']['longName'] if sender in self.nodes else 'UNK'
 		target = self.nodes[to]['user']['longName']     if to     in self.nodes else 'UNK'
 
-		logging.info(f'{id} {name} -> {target}: {msg}')
+		logging.info(f'Message recieved: {id} {name} -> {target}: {msg}')
 		print(packet)