mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Version 1.
This commit is contained in:
parent
5eee4272d7
commit
b1303832f7
8 changed files with 177 additions and 199 deletions
|
|
@ -18,7 +18,6 @@
|
|||
DD47E3DB26F3901B00029299 /* Channels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3DA26F3901A00029299 /* Channels.swift */; };
|
||||
DD47E3DD26F390A000029299 /* Messages.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3DC26F390A000029299 /* Messages.swift */; };
|
||||
DD47E3DF26F39D9F00029299 /* MyInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3DE26F39D9F00029299 /* MyInfoModel.swift */; };
|
||||
DD4A911B2708303E00501B7E /* BLEHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4A911A2708303E00501B7E /* BLEHelper.swift */; };
|
||||
DD4A911E2708C65400501B7E /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4A911D2708C65400501B7E /* AppSettings.swift */; };
|
||||
DD4A91202708C66600501B7E /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4A911F2708C66600501B7E /* Configuration.swift */; };
|
||||
DD836AE726F6B38600ABCC23 /* Connect.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD836AE626F6B38600ABCC23 /* Connect.swift */; };
|
||||
|
|
@ -78,7 +77,6 @@
|
|||
DD47E3DA26F3901A00029299 /* Channels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Channels.swift; sourceTree = "<group>"; };
|
||||
DD47E3DC26F390A000029299 /* Messages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Messages.swift; sourceTree = "<group>"; };
|
||||
DD47E3DE26F39D9F00029299 /* MyInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyInfoModel.swift; sourceTree = "<group>"; };
|
||||
DD4A911A2708303E00501B7E /* BLEHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEHelper.swift; sourceTree = "<group>"; };
|
||||
DD4A911D2708C65400501B7E /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = "<group>"; };
|
||||
DD4A911F2708C66600501B7E /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
|
||||
DD836AE626F6B38600ABCC23 /* Connect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Connect.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -113,7 +111,6 @@
|
|||
DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationHelper.swift; sourceTree = "<group>"; };
|
||||
DDF924C526FA2375009FE055 /* MessageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageModel.swift; sourceTree = "<group>"; };
|
||||
DDF924C926FBB953009FE055 /* ConnectedDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectedDevice.swift; sourceTree = "<group>"; };
|
||||
DDF924CB26FCC916009FE055 /* packets.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = packets.json; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -286,7 +283,6 @@
|
|||
DDC2E18926CE24F70042C5E4 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDF924CB26FCC916009FE055 /* packets.json */,
|
||||
);
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -318,7 +314,6 @@
|
|||
DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */,
|
||||
DDAF8C6D26ED19040058C060 /* Extensions.swift */,
|
||||
DD47E3D126F1210600029299 /* HelperFunctions.swift */,
|
||||
DD4A911A2708303E00501B7E /* BLEHelper.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -470,7 +465,6 @@
|
|||
DD47E3DB26F3901B00029299 /* Channels.swift in Sources */,
|
||||
DDAF8C6926ED0D070058C060 /* deviceonly.pb.swift in Sources */,
|
||||
DD23A51326FEF5D500D9B90C /* MessageData.swift in Sources */,
|
||||
DD4A911B2708303E00501B7E /* BLEHelper.swift in Sources */,
|
||||
DD836AED26F858F900ABCC23 /* MeshData.swift in Sources */,
|
||||
DDAF8C6B26ED0DD80058C060 /* environmental_measurement.pb.swift in Sources */,
|
||||
DD90860C26F684AF00DC5189 /* BatteryIcon.swift in Sources */,
|
||||
|
|
@ -661,7 +655,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.20;
|
||||
MARKETING_VERSION = 1.21;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
|
|
@ -688,7 +682,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.20;
|
||||
MARKETING_VERSION = 1.21;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
import Foundation
|
||||
import CoreData
|
||||
import CoreBluetooth
|
||||
import SwiftUI
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Meshtastic BLE Device Manager
|
||||
//---------------------------------------------------------------------------------------
|
||||
class BLEHelper: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate {
|
||||
|
||||
var centralManager: CBCentralManager!
|
||||
@Published var isSwitchedOn = false
|
||||
@Published var peripherals = [Peripheral]()
|
||||
|
||||
override init() {
|
||||
|
||||
super.init()
|
||||
centralManager = CBCentralManager(delegate: self, queue: nil)
|
||||
centralManager.delegate = self
|
||||
}
|
||||
|
||||
// Check for Bluetooth Connectivity
|
||||
func centralManagerDidUpdateState(_ central: CBCentralManager) {
|
||||
if central.state == .poweredOn {
|
||||
isSwitchedOn = true
|
||||
}
|
||||
else {
|
||||
isSwitchedOn = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -8,23 +8,16 @@ import SwiftUI
|
|||
//---------------------------------------------------------------------------------------
|
||||
class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate {
|
||||
|
||||
// Data
|
||||
@ObservedObject private var meshData : MeshData
|
||||
@ObservedObject private var messageData : MessageData
|
||||
|
||||
private var centralManager: CBCentralManager!
|
||||
@Published var connectedPeripheral: Peripheral!
|
||||
//@Published var peripheralArray = [CBPeripheral]()
|
||||
//@Published var connectedNodeInfo: Peripheral!
|
||||
@Published var connectedNode: NodeInfoModel!
|
||||
@Published var lastConnectedNode: String
|
||||
|
||||
//private var rssiArray = [NSNumber]()
|
||||
private var broadcastNodeId: UInt32 = 4294967295
|
||||
|
||||
@Published var isSwitchedOn = false
|
||||
@Published var peripherals = [Peripheral]()
|
||||
|
||||
private var broadcastNodeId: UInt32 = 4294967295
|
||||
|
||||
/* Meshtastic Service Details */
|
||||
var TORADIO_characteristic: CBCharacteristic!
|
||||
|
|
@ -48,7 +41,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
messageData.load()
|
||||
}
|
||||
|
||||
/* Check for Bluetooth Connectivity */
|
||||
// called when bluetooth is enabled/disabled for the app
|
||||
func centralManagerDidUpdateState(_ central: CBCentralManager) {
|
||||
if central.state == .poweredOn {
|
||||
isSwitchedOn = true
|
||||
|
|
@ -58,42 +51,98 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
}
|
||||
}
|
||||
|
||||
/* Scan for nearby BLE devices using the Meshtastic BLE service ID */
|
||||
// Scan for nearby BLE devices using the Meshtastic BLE service ID
|
||||
func startScanning() {
|
||||
|
||||
peripherals.removeAll()
|
||||
centralManager.scanForPeripherals(withServices: [meshtasticServiceCBUUID])
|
||||
print("Scanning Started")
|
||||
if isSwitchedOn {
|
||||
peripherals.removeAll()
|
||||
centralManager.scanForPeripherals(withServices: [meshtasticServiceCBUUID], options: nil)
|
||||
print("Scanning Started")
|
||||
}
|
||||
}
|
||||
|
||||
/*Stop Scanning For BLE Devices */
|
||||
// Stop Scanning For BLE Devices
|
||||
func stopScanning() {
|
||||
|
||||
self.centralManager.stopScan()
|
||||
print("Stopped Scanning")
|
||||
if centralManager.isScanning {
|
||||
|
||||
self.centralManager.stopScan()
|
||||
print("Stopped Scanning")
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect to a Device via UUID */
|
||||
func connectToDevice(id: String) {
|
||||
connectedPeripheral = peripherals.filter({ $0.peripheral.identifier.uuidString == id }).first
|
||||
lastConnectedNode = connectedPeripheral.peripheral.identifier.uuidString
|
||||
self.centralManager?.connect(connectedPeripheral!.peripheral)
|
||||
}
|
||||
|
||||
/* Disconnect Device function */
|
||||
// Disconnect Device function
|
||||
func disconnectDevice(){
|
||||
|
||||
if connectedPeripheral != nil && connectedPeripheral.peripheral.state == CBPeripheralState.connected {
|
||||
|
||||
self.centralManager?.cancelPeripheralConnection(connectedPeripheral.peripheral)
|
||||
}
|
||||
}
|
||||
|
||||
/* Send Broadcast Message */
|
||||
// Connect to a Device via UUID
|
||||
func connectToDevice(id: String) {
|
||||
|
||||
connectedPeripheral = peripherals.filter({ $0.peripheral.identifier.uuidString == id }).first
|
||||
|
||||
if connectedPeripheral != nil {
|
||||
|
||||
lastConnectedNode = connectedPeripheral.peripheral.identifier.uuidString
|
||||
self.centralManager?.connect(connectedPeripheral!.peripheral)
|
||||
print("Connected to: \(connectedPeripheral.peripheral.name ?? "Unknown")")
|
||||
}
|
||||
else {
|
||||
print("Connection failed connectedPeripheral is nil")
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to a specific peripheral
|
||||
func connectTo(peripheral: CBPeripheral) {
|
||||
|
||||
if connectedPeripheral.peripheral.state == CBPeripheralState.connected {
|
||||
disconnectDevice()
|
||||
}
|
||||
connectedPeripheral.peripheral = peripheral
|
||||
self.centralManager?.connect(connectedPeripheral!.peripheral)
|
||||
print("Connected to: \(connectedPeripheral.peripheral.name ?? "Unknown")")
|
||||
}
|
||||
|
||||
// Called each time a peripheral is discovered
|
||||
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
|
||||
|
||||
peripheral.delegate = self
|
||||
|
||||
var peripheralName: String = peripheral.name ?? "Unknown"
|
||||
|
||||
if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
|
||||
peripheralName = name
|
||||
}
|
||||
|
||||
let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, name: peripheralName, rssi: RSSI.intValue, peripheral: peripheral, myInfo: nil)
|
||||
|
||||
peripherals.append(newPeripheral)
|
||||
print("Adding peripheral: \(peripheralName)");
|
||||
}
|
||||
|
||||
// called when a peripheral is connected
|
||||
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
||||
|
||||
peripheral.delegate = self
|
||||
peripheral.discoverServices([meshtasticServiceCBUUID])
|
||||
print("Peripheral connected: " + peripheral.name!)
|
||||
startScanning()
|
||||
}
|
||||
|
||||
// Send Broadcast Message
|
||||
public func sendMessage(message: String) -> Bool
|
||||
{ var success = true
|
||||
if connectedPeripheral == nil || connectedPeripheral!.peripheral.state != CBPeripheralState.connected {
|
||||
success = false
|
||||
connectToDevice(id: lastConnectedNode)
|
||||
if lastConnectedNode.count > 10 {
|
||||
connectToDevice(id: lastConnectedNode)
|
||||
//Thread.sleep(forTimeInterval: 3)
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
|
|
@ -129,37 +178,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
}
|
||||
return success
|
||||
}
|
||||
|
||||
/* Discover Peripheral Event */
|
||||
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
|
||||
|
||||
print("Adding peripheral: " + ((peripheral.name != nil) ? peripheral.name! : "(null)"));
|
||||
|
||||
var peripheralName: String!
|
||||
peripheralName = peripheral.name
|
||||
if peripheral.name == nil {
|
||||
if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
|
||||
peripheralName = name
|
||||
}
|
||||
else {
|
||||
peripheralName = "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, name: peripheralName, rssi: RSSI.intValue, peripheral: peripheral, myInfo: nil)
|
||||
//print(newPeripheral)
|
||||
peripherals.append(newPeripheral)
|
||||
}
|
||||
|
||||
/* Connect Peripheral Event */
|
||||
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
||||
|
||||
print("Peripheral connected: " + peripheral.name!)
|
||||
peripheral.delegate = self
|
||||
peripheral.discoverServices(nil)
|
||||
}
|
||||
|
||||
/* Disconnect Peripheral Event */
|
||||
// Disconnect Peripheral Event
|
||||
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?)
|
||||
{
|
||||
|
||||
|
|
@ -178,7 +198,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
self.startScanning()
|
||||
}
|
||||
|
||||
/* Discover Services Event */
|
||||
// Discover Services Event
|
||||
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
|
||||
|
||||
guard let services = peripheral.services else { return }
|
||||
|
|
@ -190,13 +210,12 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
if (service.uuid == meshtasticServiceCBUUID)
|
||||
{
|
||||
print ("Meshtastic service OK")
|
||||
|
||||
peripheral.discoverCharacteristics(nil, for: service)
|
||||
peripheral.discoverCharacteristics([TORADIO_UUID, FROMRADIO_UUID, FROMNUM_UUID], for: service)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Discover Characteristics Event */
|
||||
// Discover Characteristics Event
|
||||
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?)
|
||||
{
|
||||
guard let characteristics = service.characteristics else { return }
|
||||
|
|
@ -233,35 +252,38 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
}
|
||||
}
|
||||
|
||||
/* Data Read / Update Characteristic Event */
|
||||
// Data Read / Update Characteristic Event
|
||||
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?)
|
||||
{
|
||||
switch characteristic.uuid
|
||||
{
|
||||
case FROMNUM_UUID:
|
||||
peripheral.readValue(for: FROMNUM_characteristic)
|
||||
peripheral.setNotifyValue(true, for: characteristic)
|
||||
print(characteristic.value ?? "no value")
|
||||
//let byteArrayFromData: [UInt8] = [UInt8](characteristic.value!)
|
||||
//let stringFromByteArray = String(data: Data(_: byteArrayFromData), encoding: .ascii)
|
||||
//print(stringFromByteArray)
|
||||
//print(characteristic.value?. ?? "no value")
|
||||
|
||||
|
||||
case FROMRADIO_UUID:
|
||||
if (characteristic.value == nil || characteristic.value!.isEmpty)
|
||||
{
|
||||
return
|
||||
}
|
||||
print(characteristic.value ?? "no value")
|
||||
print(characteristic.value ?? "no value")
|
||||
|
||||
// print(characteristic.value?.hexDescription ?? "no value")
|
||||
var decodedInfo = FromRadio()
|
||||
|
||||
decodedInfo = try! FromRadio(serializedData: characteristic.value!)
|
||||
print("Print DecodedInfo")
|
||||
print(decodedInfo)
|
||||
//print("Print DecodedInfo")
|
||||
// print(decodedInfo)
|
||||
|
||||
if decodedInfo.myInfo.myNodeNum != 0
|
||||
{
|
||||
print("Save a myInfo")
|
||||
do {
|
||||
print(try decodedInfo.myInfo.jsonString())
|
||||
// print(try decodedInfo.myInfo.jsonString())
|
||||
|
||||
// Create a MyInfoModel
|
||||
let myInfoModel = MyInfoModel(
|
||||
|
|
@ -334,7 +356,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
)
|
||||
meshData.save()
|
||||
|
||||
print(try decodedInfo.nodeInfo.jsonString())
|
||||
// print(try decodedInfo.nodeInfo.jsonString())
|
||||
} catch {
|
||||
fatalError("Failed to decode json")
|
||||
}
|
||||
|
|
@ -342,80 +364,69 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
if decodedInfo.packet.id != 0
|
||||
{
|
||||
//let byteArray = [UInt8](characteristic.value!)
|
||||
print("Try and decode packet")
|
||||
|
||||
do {
|
||||
print("Handle a Packet")
|
||||
do {
|
||||
|
||||
if decodedInfo.packet.decoded.portnum == PortNum.textMessageApp {
|
||||
|
||||
if let messageText = String(bytes: decodedInfo.packet.decoded.payload, encoding: .utf8) {
|
||||
print(messageText)
|
||||
print(try decodedInfo.packet.jsonString())
|
||||
|
||||
let broadcastNodeId: UInt32 = 4294967295
|
||||
|
||||
let fromUser = meshData.nodes.first(where: { $0.id == decodedInfo.packet.from })
|
||||
|
||||
var toUserLongName: String = "Broadcast"
|
||||
var toUserShortName: String = "BC"
|
||||
|
||||
if decodedInfo.packet.to != broadcastNodeId {
|
||||
if decodedInfo.packet.decoded.portnum == PortNum.textMessageApp {
|
||||
|
||||
if let messageText = String(bytes: decodedInfo.packet.decoded.payload, encoding: .utf8) {
|
||||
print("Message Text: \(messageText)")
|
||||
|
||||
let fromUser = meshData.nodes.first(where: { $0.id == decodedInfo.packet.from })
|
||||
|
||||
var toUserLongName: String = "Broadcast"
|
||||
var toUserShortName: String = "BC"
|
||||
|
||||
if decodedInfo.packet.to != broadcastNodeId {
|
||||
|
||||
let toUser = meshData.nodes.first(where: { $0.id == decodedInfo.packet.from })
|
||||
toUserLongName = toUser?.user.longName ?? "Unknown"
|
||||
toUserShortName = toUser?.user.shortName ?? "???"
|
||||
}
|
||||
|
||||
messageData.messages.append(
|
||||
MessageModel(messageId: decodedInfo.packet.id, messageTimeStamp: decodedInfo.packet.rxTime, fromUserId: decodedInfo.packet.from, toUserId: decodedInfo.packet.to, fromUserLongName: fromUser?.user.longName ?? "Unknown", toUserLongName: toUserLongName, fromUserShortName: fromUser?.user.shortName ?? "???", toUserShortName: toUserShortName, receivedACK: decodedInfo.packet.decoded.wantResponse, messagePayload: messageText, direction: "IN"))
|
||||
messageData.save()
|
||||
|
||||
} else {
|
||||
print("not a valid UTF-8 sequence")
|
||||
}
|
||||
|
||||
let toUser = meshData.nodes.first(where: { $0.id == decodedInfo.packet.from })
|
||||
toUserLongName = toUser?.user.longName ?? "Unknown"
|
||||
toUserShortName = toUser?.user.shortName ?? "???"
|
||||
}
|
||||
else if decodedInfo.packet.decoded.portnum == PortNum.nodeinfoApp {
|
||||
|
||||
var updatedNode = meshData.nodes.first(where: {$0.id == decodedInfo.packet.from})
|
||||
updatedNode!.snr = decodedInfo.packet.rxSnr
|
||||
updatedNode!.lastHeard = decodedInfo.packet.rxTime
|
||||
// updatedNode!.user.longName = "Node Info updated longname"
|
||||
// updatedNode!.update(from: updatedNode!.data)
|
||||
|
||||
let nodeIndex = meshData.nodes.firstIndex(where: { $0.id == decodedInfo.packet.from })
|
||||
meshData.nodes.remove(at: nodeIndex!)
|
||||
meshData.nodes.append(updatedNode!)
|
||||
meshData.save()
|
||||
print("Updated NodeInfo SNR and Time from Packet For: \(updatedNode!.user.longName)")
|
||||
}
|
||||
else if decodedInfo.packet.decoded.portnum == PortNum.positionApp {
|
||||
|
||||
messageData.messages.append(
|
||||
MessageModel(messageId: decodedInfo.packet.id, messageTimeStamp: decodedInfo.packet.rxTime, fromUserId: decodedInfo.packet.from, toUserId: decodedInfo.packet.to, fromUserLongName: fromUser?.user.longName ?? "Unknown", toUserLongName: toUserLongName, fromUserShortName: fromUser?.user.shortName ?? "???", toUserShortName: toUserShortName, receivedACK: decodedInfo.packet.decoded.wantResponse, messagePayload: messageText, direction: "IN"))
|
||||
messageData.save()
|
||||
|
||||
} else {
|
||||
print("not a valid UTF-8 sequence")
|
||||
}
|
||||
|
||||
}
|
||||
else if decodedInfo.packet.decoded.portnum == PortNum.nodeinfoApp {
|
||||
|
||||
var updatedNode = meshData.nodes.first(where: {$0.id == decodedInfo.packet.from})
|
||||
updatedNode!.snr = decodedInfo.packet.rxSnr
|
||||
updatedNode!.lastHeard = decodedInfo.packet.rxTime
|
||||
updatedNode!.update(from: updatedNode!.data)
|
||||
|
||||
if let nodeInfoPayload = String(bytes: decodedInfo.packet.decoded.payload, encoding: .ascii) {
|
||||
print(nodeInfoPayload)
|
||||
} else {
|
||||
print("not a valid UTF-8 sequence")
|
||||
print(try decodedInfo.packet.jsonString())
|
||||
}
|
||||
|
||||
}
|
||||
else if decodedInfo.packet.decoded.portnum == PortNum.positionApp {
|
||||
|
||||
//Set time and snr from nodeinfo
|
||||
if let nodeInfoPayload = String(bytes: decodedInfo.packet.decoded.payload, encoding: .unicode) {
|
||||
print(nodeInfoPayload)
|
||||
} else {
|
||||
print("not a valid UTF-8 sequence")
|
||||
print(try decodedInfo.packet.jsonString())
|
||||
}
|
||||
}
|
||||
else if decodedInfo.packet.decoded.portnum == PortNum.adminApp {
|
||||
|
||||
//Set time and snr from nodeinfo
|
||||
if let nodeInfoPayload = String(bytes: decodedInfo.packet.decoded.payload, encoding: .unicode) {
|
||||
print(nodeInfoPayload)
|
||||
} else {
|
||||
print("not a valid UTF-8 sequence")
|
||||
print(try decodedInfo.packet.jsonString())
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print("Save a packet")
|
||||
print(try decodedInfo.packet.jsonString())
|
||||
}
|
||||
print("Postion Payload")
|
||||
print(try decodedInfo.packet.jsonString())
|
||||
}
|
||||
else if decodedInfo.packet.decoded.portnum == PortNum.adminApp {
|
||||
|
||||
print("Admin App Packet")
|
||||
print(try decodedInfo.packet.jsonString())
|
||||
}
|
||||
else if decodedInfo.packet.decoded.portnum == PortNum.routingApp {
|
||||
|
||||
print("Routing App Packet")
|
||||
//print(try decodedInfo.packet.jsonString())
|
||||
}
|
||||
else
|
||||
{
|
||||
print("Other App Packet")
|
||||
print(try decodedInfo.packet.jsonString())
|
||||
}
|
||||
|
||||
} catch {
|
||||
fatalError("Failed to decode json")
|
||||
|
|
@ -423,15 +434,13 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
}
|
||||
|
||||
if decodedInfo.configCompleteID != 0 {
|
||||
print(decodedInfo)
|
||||
print("Config Complete: \(decodedInfo)")
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
print("Unhandled Characteristic UUID: \(characteristic.uuid)")
|
||||
}
|
||||
|
||||
peripheral.readValue(for: FROMRADIO_characteristic)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
[
|
||||
{
|
||||
"from":4064715620,
|
||||
"to":4294967295,
|
||||
"decoded":{
|
||||
"portnum":"TEXT_MESSAGE_APP",
|
||||
"payload":"YmFsbHM="
|
||||
|
||||
},
|
||||
"id":3773493287,
|
||||
"rxTime":1632407404,
|
||||
"rxSnr":10.75,
|
||||
"hopLimit":3}
|
||||
]
|
||||
|
|
@ -142,6 +142,9 @@ struct Connect: View {
|
|||
}
|
||||
)
|
||||
}.navigationViewStyle(StackNavigationViewStyle())
|
||||
.onAppear{
|
||||
bleManager.startScanning()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,13 @@ struct Messages: View {
|
|||
if bleManager.sendMessage(message: typingMessage) {
|
||||
typingMessage = ""
|
||||
}
|
||||
else {
|
||||
let timer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false) { (timer) in
|
||||
if bleManager.sendMessage(message: typingMessage) {
|
||||
typingMessage = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} ) {
|
||||
Image(systemName: "arrow.up.circle.fill").font(.largeTitle).foregroundColor(.blue)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,15 @@ struct NodeList: View {
|
|||
}
|
||||
ForEach(filteredDevices.sorted(by: { $0.lastHeard > $1.lastHeard })) { node in
|
||||
NavigationLink(destination: NodeDetail(node: node)) {
|
||||
NodeRow(node: node, index : 0)
|
||||
|
||||
if(bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.myInfo != nil) {
|
||||
|
||||
let connected: Bool = (bleManager.connectedPeripheral.myInfo!.id == node.id)
|
||||
NodeRow(node: node, connected: connected)
|
||||
}
|
||||
else {
|
||||
NodeRow(node: node, connected: false)
|
||||
}
|
||||
|
||||
}
|
||||
.swipeActions {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import SwiftUI
|
|||
|
||||
struct NodeRow: View {
|
||||
var node: NodeInfoModel
|
||||
var index: Int
|
||||
var connected: Bool
|
||||
|
||||
var body: some View {
|
||||
VStack (alignment: .leading) {
|
||||
|
|
@ -18,7 +18,10 @@ struct NodeRow: View {
|
|||
|
||||
Image(systemName: "timer").font(.headline).foregroundColor(.blue).symbolRenderingMode(.hierarchical)
|
||||
|
||||
if node.lastHeard > 0 {
|
||||
if connected {
|
||||
Text("Currently Connected").font(.subheadline).foregroundColor(Color.accentColor)
|
||||
}
|
||||
else if node.lastHeard > 0 {
|
||||
let lastHeard = Date(timeIntervalSince1970: TimeInterval(node.lastHeard))
|
||||
Text("Last Heard: \(lastHeard, style: .relative) ago").font(.subheadline).foregroundColor(.gray)
|
||||
}
|
||||
|
|
@ -35,7 +38,7 @@ struct NodeRow_Previews: PreviewProvider {
|
|||
|
||||
static var previews: some View {
|
||||
Group {
|
||||
NodeRow(node: nodes[0], index: 0)
|
||||
NodeRow(node: nodes[0], connected: true)
|
||||
}
|
||||
.previewLayout(.fixed(width: 300, height: 70))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue