Some checks failed
Test and build / Build receiver (amd64, , linux) (push) Failing after 40s
Test and build / Build receiver (arm, 6, linux) (push) Failing after 41s
Test and build / Build receiver (arm, 7, linux) (push) Failing after 40s
Test and build / Build collector (push) Failing after 54s
Test and build / test (push) Successful in 59s
184 lines
4.1 KiB
Go
184 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/urfave/cli/v3"
|
|
|
|
"git.maze.io/go/ham/protocol/meshcore"
|
|
|
|
"git.maze.io/ham/hamview"
|
|
"git.maze.io/ham/hamview/cmd"
|
|
|
|
_ "github.com/cridenour/go-postgis" // PostGIS support
|
|
_ "github.com/lib/pq" // PostgreSQL support
|
|
)
|
|
|
|
var logger = logrus.New()
|
|
|
|
/*
|
|
{
|
|
"public_key": "E119666239EE254E8E7B2937A99FE9DB7CBB58040B5D0E995B719C598CD261F6",
|
|
"name": "~ Jonzy Heltec Repeater",
|
|
"device_role": 2,
|
|
"regions": [
|
|
"OMA"
|
|
],
|
|
"first_seen": "2026-01-18T04:31:21.694Z",
|
|
"last_seen": "2026-02-20T10:30:16.144Z",
|
|
"is_mqtt_connected": true,
|
|
"decoded_payload": {
|
|
"lat": 41.28516,
|
|
"lon": -96.13876,
|
|
"mode": "Repeater",
|
|
"name": "~ Jonzy Heltec Repeater",
|
|
"flags": 146,
|
|
"is_valid": true,
|
|
"signature": "F08599E4D7357E9276B5F78246C698BFFCF14EC83D8A70CAB6F8E63EDF3FEB5CB692A60C3072593ABE0261B164709F9E012AC526B5EF08407B3520C13719900E",
|
|
"timestamp": 1771583405,
|
|
"public_key": "E119666239EE254E8E7B2937A99FE9DB7CBB58040B5D0E995B719C598CD261F6"
|
|
},
|
|
"location": {
|
|
"latitude": 41.28516,
|
|
"longitude": -96.13876
|
|
},
|
|
"node_settings": {
|
|
"show_neighbors": true,
|
|
"show_adverts": true
|
|
}
|
|
},
|
|
*/
|
|
type node struct {
|
|
PublicKey string `json:"public_key"`
|
|
Name string `json:"name"`
|
|
Type int `json:"device_role"`
|
|
FirstHeard time.Time `json:"first_seen"`
|
|
LastHeard time.Time `json:"last_seen"`
|
|
Position *meshcore.Position `json:"location"`
|
|
Payload payload `json:"decoded_payload`
|
|
}
|
|
|
|
type payload struct {
|
|
Timestamp int64 `json:"timestamp"`
|
|
}
|
|
|
|
func main() {
|
|
cmd := &cli.Command{
|
|
Name: "import-letsmesh-nodes",
|
|
Action: run,
|
|
Before: cmd.ConfigureLogging(&logger),
|
|
Flags: append([]cli.Flag{
|
|
&cli.StringFlag{
|
|
Name: "dump",
|
|
Usage: "letsmesh node json",
|
|
Value: "letsmeshnodes.json",
|
|
},
|
|
}, cmd.AllFlags("hamview-collector.yaml")...),
|
|
}
|
|
|
|
if err := cmd.Run(context.Background(), os.Args); err != nil {
|
|
logger.Fatal(err)
|
|
}
|
|
}
|
|
|
|
type collectorConfig struct {
|
|
hamview.CollectorConfig `yaml:",inline"`
|
|
Broker map[string]any `yaml:"broker"`
|
|
Meshcore map[string]any `yaml:"meshcore"`
|
|
Include []string
|
|
}
|
|
|
|
func (config *collectorConfig) Includes() []string {
|
|
includes := config.Include
|
|
config.Include = nil
|
|
return includes
|
|
}
|
|
|
|
func run(ctx context.Context, command *cli.Command) error {
|
|
var config collectorConfig
|
|
if err := cmd.Load(logger, command.String(cmd.FlagConfig), &config); err != nil {
|
|
return err
|
|
}
|
|
|
|
db, err := sql.Open(config.Database.Type, config.Database.Conf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer db.Close()
|
|
|
|
b, err := os.ReadFile(command.String("dump"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var nodes struct {
|
|
Nodes []*node `json:"nodes"`
|
|
}
|
|
if err = json.Unmarshal(b, &nodes); err != nil {
|
|
return err
|
|
}
|
|
|
|
logger.Infof("found %d nodes", len(nodes.Nodes))
|
|
for _, node := range nodes.Nodes {
|
|
k, err := hex.DecodeString(node.PublicKey)
|
|
if err != nil {
|
|
logger.Warnf("node %s has incorrect public key: %v", node.Name, err)
|
|
continue
|
|
}
|
|
logger.Infof("node %s at %s", node.Name, node.Position)
|
|
var latitude, longitude *float64
|
|
if node.Position != nil {
|
|
latitude = &node.Position.Latitude
|
|
longitude = &node.Position.Longitude
|
|
}
|
|
if _, err = db.Exec(
|
|
`INSERT INTO meshcore_node (
|
|
node_type,
|
|
public_key,
|
|
name,
|
|
local_time,
|
|
first_heard,
|
|
last_heard,
|
|
last_latitude,
|
|
last_longitude
|
|
) VALUES (
|
|
$1,
|
|
$2,
|
|
$3,
|
|
$4,
|
|
$5,
|
|
$6,
|
|
$7,
|
|
$8
|
|
)
|
|
ON CONFLICT (public_key)
|
|
DO UPDATE
|
|
SET
|
|
name = $3,
|
|
local_time = $4,
|
|
last_heard = $6,
|
|
last_latitude = $7,
|
|
last_longitude = $8
|
|
`,
|
|
node.Type,
|
|
k,
|
|
node.Name,
|
|
time.Unix(node.Payload.Timestamp, 0),
|
|
node.FirstHeard,
|
|
node.LastHeard,
|
|
latitude,
|
|
longitude,
|
|
); err != nil {
|
|
logger.Fatalf("node %s insert failed: %v", node.Name, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|