mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
refactor(MeshLog): add fields for query optimization
- Adds `from_num` and `port_num` fields as indices to the `MeshLog` entity to improve query performance. - Sets default values for new columns for auto-migration and backward compatibility.
This commit is contained in:
parent
a075dfbd3a
commit
717c932ae2
7 changed files with 800 additions and 55 deletions
|
|
@ -0,0 +1,696 @@
|
|||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 12,
|
||||
"identityHash": "293c8875bddb0da5cdeb7e1903dc9c38",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "MyNodeInfo",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`myNodeNum` INTEGER NOT NULL, `hasGPS` INTEGER NOT NULL, `model` TEXT, `firmwareVersion` TEXT, `couldUpdate` INTEGER NOT NULL, `shouldUpdate` INTEGER NOT NULL, `currentPacketId` INTEGER NOT NULL, `messageTimeoutMsec` INTEGER NOT NULL, `minAppVersion` INTEGER NOT NULL, `maxChannels` INTEGER NOT NULL, `hasWifi` INTEGER NOT NULL, `channelUtilization` REAL NOT NULL, `airUtilTx` REAL NOT NULL, PRIMARY KEY(`myNodeNum`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "myNodeNum",
|
||||
"columnName": "myNodeNum",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "hasGPS",
|
||||
"columnName": "hasGPS",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "model",
|
||||
"columnName": "model",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "firmwareVersion",
|
||||
"columnName": "firmwareVersion",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "couldUpdate",
|
||||
"columnName": "couldUpdate",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "shouldUpdate",
|
||||
"columnName": "shouldUpdate",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "currentPacketId",
|
||||
"columnName": "currentPacketId",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "messageTimeoutMsec",
|
||||
"columnName": "messageTimeoutMsec",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "minAppVersion",
|
||||
"columnName": "minAppVersion",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "maxChannels",
|
||||
"columnName": "maxChannels",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "hasWifi",
|
||||
"columnName": "hasWifi",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "channelUtilization",
|
||||
"columnName": "channelUtilization",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "airUtilTx",
|
||||
"columnName": "airUtilTx",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"myNodeNum"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "NodeInfo",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`num` INTEGER NOT NULL, `snr` REAL NOT NULL, `rssi` INTEGER NOT NULL, `lastHeard` INTEGER NOT NULL, `channel` INTEGER NOT NULL, `hopsAway` INTEGER NOT NULL DEFAULT 0, `user_id` TEXT, `user_longName` TEXT, `user_shortName` TEXT, `user_hwModel` TEXT, `user_isLicensed` INTEGER, `user_role` INTEGER DEFAULT 0, `position_latitude` REAL, `position_longitude` REAL, `position_altitude` INTEGER, `position_time` INTEGER, `position_satellitesInView` INTEGER, `position_groundSpeed` INTEGER, `position_groundTrack` INTEGER, `position_precisionBits` INTEGER, `devMetrics_time` INTEGER, `devMetrics_batteryLevel` INTEGER, `devMetrics_voltage` REAL, `devMetrics_channelUtilization` REAL, `devMetrics_airUtilTx` REAL, `devMetrics_uptimeSeconds` INTEGER, `envMetrics_time` INTEGER, `envMetrics_temperature` REAL, `envMetrics_relativeHumidity` REAL, `envMetrics_barometricPressure` REAL, `envMetrics_gasResistance` REAL, `envMetrics_voltage` REAL, `envMetrics_current` REAL, `envMetrics_iaq` INTEGER, PRIMARY KEY(`num`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "num",
|
||||
"columnName": "num",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snr",
|
||||
"columnName": "snr",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "rssi",
|
||||
"columnName": "rssi",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastHeard",
|
||||
"columnName": "lastHeard",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "channel",
|
||||
"columnName": "channel",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "hopsAway",
|
||||
"columnName": "hopsAway",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "user.id",
|
||||
"columnName": "user_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "user.longName",
|
||||
"columnName": "user_longName",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "user.shortName",
|
||||
"columnName": "user_shortName",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "user.hwModel",
|
||||
"columnName": "user_hwModel",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "user.isLicensed",
|
||||
"columnName": "user_isLicensed",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "user.role",
|
||||
"columnName": "user_role",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "position.latitude",
|
||||
"columnName": "position_latitude",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "position.longitude",
|
||||
"columnName": "position_longitude",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "position.altitude",
|
||||
"columnName": "position_altitude",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "position.time",
|
||||
"columnName": "position_time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "position.satellitesInView",
|
||||
"columnName": "position_satellitesInView",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "position.groundSpeed",
|
||||
"columnName": "position_groundSpeed",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "position.groundTrack",
|
||||
"columnName": "position_groundTrack",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "position.precisionBits",
|
||||
"columnName": "position_precisionBits",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "deviceMetrics.time",
|
||||
"columnName": "devMetrics_time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "deviceMetrics.batteryLevel",
|
||||
"columnName": "devMetrics_batteryLevel",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "deviceMetrics.voltage",
|
||||
"columnName": "devMetrics_voltage",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "deviceMetrics.channelUtilization",
|
||||
"columnName": "devMetrics_channelUtilization",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "deviceMetrics.airUtilTx",
|
||||
"columnName": "devMetrics_airUtilTx",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "deviceMetrics.uptimeSeconds",
|
||||
"columnName": "devMetrics_uptimeSeconds",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "environmentMetrics.time",
|
||||
"columnName": "envMetrics_time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "environmentMetrics.temperature",
|
||||
"columnName": "envMetrics_temperature",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "environmentMetrics.relativeHumidity",
|
||||
"columnName": "envMetrics_relativeHumidity",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "environmentMetrics.barometricPressure",
|
||||
"columnName": "envMetrics_barometricPressure",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "environmentMetrics.gasResistance",
|
||||
"columnName": "envMetrics_gasResistance",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "environmentMetrics.voltage",
|
||||
"columnName": "envMetrics_voltage",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "environmentMetrics.current",
|
||||
"columnName": "envMetrics_current",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "environmentMetrics.iaq",
|
||||
"columnName": "envMetrics_iaq",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"num"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "nodes",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`num` INTEGER NOT NULL, `user` BLOB NOT NULL, `long_name` TEXT, `short_name` TEXT, `position` BLOB NOT NULL, `latitude` REAL NOT NULL, `longitude` REAL NOT NULL, `snr` REAL NOT NULL, `rssi` INTEGER NOT NULL, `last_heard` INTEGER NOT NULL, `device_metrics` BLOB NOT NULL, `channel` INTEGER NOT NULL, `via_mqtt` INTEGER NOT NULL, `hops_away` INTEGER NOT NULL, `is_favorite` INTEGER NOT NULL, `environment_metrics` BLOB NOT NULL, `power_metrics` BLOB NOT NULL, `paxcounter` BLOB NOT NULL, PRIMARY KEY(`num`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "num",
|
||||
"columnName": "num",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "user",
|
||||
"columnName": "user",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "longName",
|
||||
"columnName": "long_name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "shortName",
|
||||
"columnName": "short_name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "latitude",
|
||||
"columnName": "latitude",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "longitude",
|
||||
"columnName": "longitude",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snr",
|
||||
"columnName": "snr",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "rssi",
|
||||
"columnName": "rssi",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastHeard",
|
||||
"columnName": "last_heard",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "deviceTelemetry",
|
||||
"columnName": "device_metrics",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "channel",
|
||||
"columnName": "channel",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "viaMqtt",
|
||||
"columnName": "via_mqtt",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "hopsAway",
|
||||
"columnName": "hops_away",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isFavorite",
|
||||
"columnName": "is_favorite",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "environmentTelemetry",
|
||||
"columnName": "environment_metrics",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "powerTelemetry",
|
||||
"columnName": "power_metrics",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "paxcounter",
|
||||
"columnName": "paxcounter",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"num"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "packet",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `myNodeNum` INTEGER NOT NULL DEFAULT 0, `port_num` INTEGER NOT NULL, `contact_key` TEXT NOT NULL, `received_time` INTEGER NOT NULL, `read` INTEGER NOT NULL DEFAULT 1, `data` TEXT NOT NULL, `packet_id` INTEGER NOT NULL DEFAULT 0, `routing_error` INTEGER NOT NULL DEFAULT -1)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uuid",
|
||||
"columnName": "uuid",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "myNodeNum",
|
||||
"columnName": "myNodeNum",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "port_num",
|
||||
"columnName": "port_num",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "contact_key",
|
||||
"columnName": "contact_key",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "received_time",
|
||||
"columnName": "received_time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "read",
|
||||
"columnName": "read",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "1"
|
||||
},
|
||||
{
|
||||
"fieldPath": "data",
|
||||
"columnName": "data",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "packetId",
|
||||
"columnName": "packet_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "routingError",
|
||||
"columnName": "routing_error",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "-1"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"uuid"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_packet_myNodeNum",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"myNodeNum"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_packet_myNodeNum` ON `${TABLE_NAME}` (`myNodeNum`)"
|
||||
},
|
||||
{
|
||||
"name": "index_packet_port_num",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"port_num"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_packet_port_num` ON `${TABLE_NAME}` (`port_num`)"
|
||||
},
|
||||
{
|
||||
"name": "index_packet_contact_key",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"contact_key"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_packet_contact_key` ON `${TABLE_NAME}` (`contact_key`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "contact_settings",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`contact_key` TEXT NOT NULL, `muteUntil` INTEGER NOT NULL, PRIMARY KEY(`contact_key`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "contact_key",
|
||||
"columnName": "contact_key",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "muteUntil",
|
||||
"columnName": "muteUntil",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"contact_key"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "log",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `type` TEXT NOT NULL, `received_date` INTEGER NOT NULL, `message` TEXT NOT NULL, `from_num` INTEGER NOT NULL DEFAULT 0, `port_num` INTEGER NOT NULL DEFAULT 0, `from_radio` BLOB NOT NULL DEFAULT x'', PRIMARY KEY(`uuid`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uuid",
|
||||
"columnName": "uuid",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "message_type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "received_date",
|
||||
"columnName": "received_date",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "raw_message",
|
||||
"columnName": "message",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "fromNum",
|
||||
"columnName": "from_num",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "portNum",
|
||||
"columnName": "port_num",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "fromRadio",
|
||||
"columnName": "from_radio",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true,
|
||||
"defaultValue": "x''"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"uuid"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_log_from_num",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"from_num"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_log_from_num` ON `${TABLE_NAME}` (`from_num`)"
|
||||
},
|
||||
{
|
||||
"name": "index_log_port_num",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"port_num"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_log_port_num` ON `${TABLE_NAME}` (`port_num`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "quick_chat",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `message` TEXT NOT NULL, `mode` TEXT NOT NULL, `position` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uuid",
|
||||
"columnName": "uuid",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "message",
|
||||
"columnName": "message",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "mode",
|
||||
"columnName": "mode",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"uuid"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '293c8875bddb0da5cdeb7e1903dc9c38')"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import com.geeksville.mesh.android.Logging
|
|||
import com.google.protobuf.InvalidProtocolBufferException
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class Converters : Logging {
|
||||
@TypeConverter
|
||||
fun dataFromString(value: String): DataPacket {
|
||||
|
|
@ -22,6 +23,21 @@ class Converters : Logging {
|
|||
return json.encodeToString(DataPacket.serializer(), value)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun bytesToFromRadio(bytes: ByteArray): MeshProtos.FromRadio {
|
||||
return try {
|
||||
MeshProtos.FromRadio.parseFrom(bytes)
|
||||
} catch (ex: InvalidProtocolBufferException) {
|
||||
errormsg("bytesToFromRadio TypeConverter error:", ex)
|
||||
MeshProtos.FromRadio.getDefaultInstance()
|
||||
}
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromRadioToBytes(value: MeshProtos.FromRadio): ByteArray? {
|
||||
return value.toByteArray()
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun bytesToUser(bytes: ByteArray): MeshProtos.User {
|
||||
return try {
|
||||
|
|
|
|||
|
|
@ -26,17 +26,15 @@ class MeshLogRepository @Inject constructor(private val meshLogDaoLazy: dagger.L
|
|||
meshLogDao.getAllLogsInReceiveOrder(maxItems)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun getMeshPacketsFrom(nodeNum: Int) = meshLogDao.getAllLogs(MAX_MESH_PACKETS)
|
||||
.mapLatest { list -> list.mapNotNull { it.meshPacket }.filter { it.from == nodeNum } }
|
||||
.distinctUntilChanged()
|
||||
.flowOn(Dispatchers.IO)
|
||||
private fun parseTelemetryLog(log: MeshLog): Telemetry? =
|
||||
runCatching { Telemetry.parseFrom(log.fromRadio.packet.decoded.payload) }.getOrNull()
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun getTelemetryFrom(nodeNum: Int) = getMeshPacketsFrom(nodeNum).mapLatest { list ->
|
||||
list.filter { it.hasDecoded() && it.decoded.portnum == Portnums.PortNum.TELEMETRY_APP }
|
||||
.mapNotNull { runCatching { Telemetry.parseFrom(it.decoded.payload) }.getOrNull() }
|
||||
}.flowOn(Dispatchers.IO)
|
||||
fun getTelemetryFrom(nodeNum: Int): Flow<List<Telemetry>> =
|
||||
meshLogDao.getLogsFrom(nodeNum, Portnums.PortNum.TELEMETRY_APP_VALUE, MAX_MESH_PACKETS)
|
||||
.distinctUntilChanged()
|
||||
.mapLatest { list -> list.mapNotNull(::parseTelemetryLog) }
|
||||
.flowOn(Dispatchers.IO)
|
||||
|
||||
suspend fun insert(log: MeshLog) = withContext(Dispatchers.IO) {
|
||||
meshLogDao.insert(log)
|
||||
|
|
|
|||
|
|
@ -37,8 +37,9 @@ import com.geeksville.mesh.database.entity.QuickChatAction
|
|||
AutoMigration (from = 8, to = 9),
|
||||
AutoMigration (from = 9, to = 10),
|
||||
AutoMigration (from = 10, to = 11),
|
||||
AutoMigration (from = 11, to = 12),
|
||||
],
|
||||
version = 11,
|
||||
version = 12,
|
||||
exportSchema = true,
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
|
|
|
|||
|
|
@ -9,16 +9,25 @@ import kotlinx.coroutines.flow.Flow
|
|||
@Dao
|
||||
interface MeshLogDao {
|
||||
|
||||
@Query("Select * from log order by received_date desc limit 0,:maxItem")
|
||||
@Query("SELECT * FROM log ORDER BY received_date DESC LIMIT 0,:maxItem")
|
||||
fun getAllLogs(maxItem: Int): Flow<List<MeshLog>>
|
||||
|
||||
@Query("Select * from log order by received_date asc limit 0,:maxItem")
|
||||
@Query("SELECT * FROM log ORDER BY received_date ASC LIMIT 0,:maxItem")
|
||||
fun getAllLogsInReceiveOrder(maxItem: Int): Flow<List<MeshLog>>
|
||||
|
||||
@Query(
|
||||
"""
|
||||
SELECT * FROM log
|
||||
WHERE from_num = :fromNum AND port_num = :portNum
|
||||
ORDER BY received_date DESC LIMIT 0,:maxItem
|
||||
"""
|
||||
)
|
||||
fun getLogsFrom(fromNum: Int, portNum: Int, maxItem: Int): Flow<List<MeshLog>>
|
||||
|
||||
@Insert
|
||||
fun insert(log: MeshLog)
|
||||
|
||||
@Query("DELETE from log")
|
||||
@Query("DELETE FROM log")
|
||||
fun deleteAll()
|
||||
|
||||
}
|
||||
|
|
@ -2,18 +2,30 @@ package com.geeksville.mesh.database.entity
|
|||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
import com.geeksville.mesh.MeshProtos
|
||||
import com.geeksville.mesh.MeshProtos.FromRadio
|
||||
import com.geeksville.mesh.Portnums
|
||||
import com.google.protobuf.TextFormat
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
@Entity(tableName = "log")
|
||||
data class MeshLog(@PrimaryKey val uuid: String,
|
||||
@ColumnInfo(name = "type") val message_type: String,
|
||||
@ColumnInfo(name = "received_date") val received_date: Long,
|
||||
@ColumnInfo(name = "message") val raw_message: String
|
||||
@Entity(
|
||||
tableName = "log",
|
||||
indices = [
|
||||
Index(value = ["from_num"]),
|
||||
Index(value = ["port_num"]),
|
||||
],
|
||||
)
|
||||
data class MeshLog(
|
||||
@PrimaryKey val uuid: String,
|
||||
@ColumnInfo(name = "type") val message_type: String,
|
||||
@ColumnInfo(name = "received_date") val received_date: Long,
|
||||
@ColumnInfo(name = "message") val raw_message: String,
|
||||
@ColumnInfo(name = "from_num", defaultValue = "0") val fromNum: Int = 0,
|
||||
@ColumnInfo(name = "port_num", defaultValue = "0") val portNum: Int = 0,
|
||||
@ColumnInfo(name = "from_radio", typeAffinity = ColumnInfo.BLOB, defaultValue = "x''")
|
||||
val fromRadio: FromRadio = FromRadio.getDefaultInstance(),
|
||||
) {
|
||||
|
||||
val meshPacket: MeshProtos.MeshPacket?
|
||||
|
|
|
|||
|
|
@ -216,10 +216,13 @@ class MeshService : Service(), Logging {
|
|||
|
||||
if (p.packet.hasDecoded()) {
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"Packet",
|
||||
System.currentTimeMillis(),
|
||||
p.packet.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "Packet",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = p.packet.toString(),
|
||||
fromNum = p.packet.from,
|
||||
portNum = p.packet.decoded.portnumValue,
|
||||
fromRadio = fromRadio { packet = p.packet },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
}
|
||||
|
|
@ -1061,10 +1064,13 @@ class MeshService : Service(), Logging {
|
|||
// debug("Recieved: $packet")
|
||||
if (packet.hasDecoded()) {
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"Packet",
|
||||
System.currentTimeMillis(),
|
||||
packet.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "Packet",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = packet.toString(),
|
||||
fromNum = packet.from,
|
||||
portNum = packet.decoded.portnumValue,
|
||||
fromRadio = fromRadio { this.packet = packet },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
|
||||
|
|
@ -1320,10 +1326,11 @@ class MeshService : Service(), Logging {
|
|||
private fun handleDeviceConfig(config: ConfigProtos.Config) {
|
||||
debug("Received config ${config.toOneLineString()}")
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"Config ${config.payloadVariantCase}",
|
||||
System.currentTimeMillis(),
|
||||
config.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "Config ${config.payloadVariantCase}",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = config.toString(),
|
||||
fromRadio = fromRadio { this.config = config },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
setLocalConfig(config)
|
||||
|
|
@ -1334,10 +1341,11 @@ class MeshService : Service(), Logging {
|
|||
private fun handleModuleConfig(config: ModuleConfigProtos.ModuleConfig) {
|
||||
debug("Received moduleConfig ${config.toOneLineString()}")
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"ModuleConfig ${config.payloadVariantCase}",
|
||||
System.currentTimeMillis(),
|
||||
config.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "ModuleConfig ${config.payloadVariantCase}",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = config.toString(),
|
||||
fromRadio = fromRadio { moduleConfig = config },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
setLocalModuleConfig(config)
|
||||
|
|
@ -1358,10 +1366,11 @@ class MeshService : Service(), Logging {
|
|||
private fun handleChannel(ch: ChannelProtos.Channel) {
|
||||
debug("Received channel ${ch.index}")
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"Channel",
|
||||
System.currentTimeMillis(),
|
||||
ch.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "Channel",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = ch.toString(),
|
||||
fromRadio = fromRadio { channel = ch },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
if (ch.role != ChannelProtos.Channel.Role.DISABLED) updateChannelSettings(ch)
|
||||
|
|
@ -1404,10 +1413,11 @@ class MeshService : Service(), Logging {
|
|||
debug("Received nodeinfo num=${info.num}, hasUser=${info.hasUser()}, hasPosition=${info.hasPosition()}, hasDeviceMetrics=${info.hasDeviceMetrics()}")
|
||||
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"NodeInfo",
|
||||
System.currentTimeMillis(),
|
||||
info.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "NodeInfo",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = info.toString(),
|
||||
fromRadio = fromRadio { nodeInfo = info },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
|
||||
|
|
@ -1465,10 +1475,11 @@ class MeshService : Service(), Logging {
|
|||
*/
|
||||
private fun handleMyInfo(myInfo: MeshProtos.MyNodeInfo) {
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"MyNodeInfo",
|
||||
System.currentTimeMillis(),
|
||||
myInfo.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "MyNodeInfo",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = myInfo.toString(),
|
||||
fromRadio = fromRadio { this.myInfo = myInfo },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
|
||||
|
|
@ -1488,10 +1499,11 @@ class MeshService : Service(), Logging {
|
|||
private fun handleMetadata(metadata: MeshProtos.DeviceMetadata) {
|
||||
debug("Received deviceMetadata ${metadata.toOneLineString()}")
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"DeviceMetadata",
|
||||
System.currentTimeMillis(),
|
||||
metadata.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "DeviceMetadata",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = metadata.toString(),
|
||||
fromRadio = fromRadio { this.metadata = metadata },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
|
||||
|
|
@ -1561,10 +1573,11 @@ class MeshService : Service(), Logging {
|
|||
if (configCompleteId == configNonce) {
|
||||
|
||||
val packetToSave = MeshLog(
|
||||
UUID.randomUUID().toString(),
|
||||
"ConfigComplete",
|
||||
System.currentTimeMillis(),
|
||||
configCompleteId.toString()
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
message_type = "ConfigComplete",
|
||||
received_date = System.currentTimeMillis(),
|
||||
raw_message = configCompleteId.toString(),
|
||||
fromRadio = fromRadio { this.configCompleteId = configCompleteId },
|
||||
)
|
||||
insertMeshLog(packetToSave)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue