This commit is contained in:
Martin/Geno 2018-08-10 13:46:18 +02:00
parent a641a162a0
commit cfcb3859ca
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
22 changed files with 143 additions and 164 deletions

View File

@ -7,7 +7,7 @@ webroot = "./webroot/"
secret = "passw0rd" secret = "passw0rd"
ssh_key = "~/.ssh/id_rsa" ssh_key = "~/.ssh/id_rsa"
ssh_ipaddress_suffix = "fd2f:" ssh_ipaddress_prefix = "fd2f:"
ssh_timeout = "1m" ssh_timeout = "1m"
# enable receiving # enable receiving

View File

@ -53,9 +53,9 @@ func main() {
sshmanager := ssh.NewManager(config.SSHPrivateKey, config.SSHTimeout.Duration) sshmanager := ssh.NewManager(config.SSHPrivateKey, config.SSHTimeout.Duration)
nodesYanic := runtimeYanic.NewNodes(&runtimeYanic.NodesConfig{}) nodesYanic := runtimeYanic.NewNodes(&runtimeYanic.NodesConfig{})
ws := websocket.NewWebsocketServer(config.Secret, db, nodesYanic) ws := websocket.NewWebsocketServer(config.Secret, config.SSHIPAddressPrefix, db, nodesYanic)
yanic := runtime.NewYanicDB(db, sshmanager, ws.SendNode, ws.SendStats, config.SSHIPAddressSuffix) yanic := runtime.NewYanicDB(db, sshmanager, ws.SendNode, ws.SendStats, config.SSHIPAddressPrefix)
if config.YanicEnable { if config.YanicEnable {
if duration := config.YanicSynchronize.Duration; duration > 0 { if duration := config.YanicSynchronize.Duration; duration > 0 {

View File

@ -10,21 +10,21 @@ func TestChannel(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
ChannelEU = true ChannelEU = true
assert.False(ChannelIs5GHz(11), "is 2.4 GHz in EU") assert.False(ChannelIs5GHz(9), "is 2.4 GHz in EU")
assert.True(ChannelIs5GHz(40), "is 5 GHz everywhere") assert.True(ChannelIs5GHz(44), "is 5 GHz everywhere")
assert.False(ChannelIs5GHz(42), "is not 5 GHz in EU") assert.False(ChannelIs5GHz(38), "is not 5 GHz in EU")
assert.NotNil(GetChannel(11), "is 2.4 GHz channel everywhere") assert.NotNil(GetChannel(9), "is 2.4 GHz channel everywhere")
assert.NotNil(GetChannel(40), "is 5 GHz channel everywhere") assert.NotNil(GetChannel(44), "is 5 GHz channel everywhere")
assert.Nil(GetChannel(42), "is not a 5 GHz channel in EU") assert.Nil(GetChannel(38), "is not a 5 GHz channel in EU")
ChannelEU = false ChannelEU = false
assert.False(ChannelIs5GHz(11), "is 2.4 GHz in EU") assert.False(ChannelIs5GHz(9), "is 2.4 GHz in EU")
assert.True(ChannelIs5GHz(40), "is 5 GHz everywhere") assert.True(ChannelIs5GHz(44), "is 5 GHz everywhere")
assert.True(ChannelIs5GHz(42), "is 5 GHz somewhere else") assert.True(ChannelIs5GHz(38), "is 5 GHz somewhere else")
assert.NotNil(GetChannel(11), "is 2.4 GHz channel everywhere") assert.NotNil(GetChannel(9), "is 2.4 GHz channel everywhere")
assert.NotNil(GetChannel(40), "is 5 GHz channel everywhere") assert.NotNil(GetChannel(44), "is 5 GHz channel everywhere")
assert.NotNil(GetChannel(42), "is 5 GHz channel somewhere else") assert.NotNil(GetChannel(38), "is 5 GHz channel somewhere else")
} }

View File

@ -22,7 +22,7 @@ type Config struct {
// SSH private key // SSH private key
SSHPrivateKey string `toml:"ssh_key"` SSHPrivateKey string `toml:"ssh_key"`
SSHIPAddressSuffix string `toml:"ssh_ipaddress_suffix"` SSHIPAddressPrefix string `toml:"ssh_ipaddress_prefix"`
SSHTimeout duration.Duration `toml:"ssh_timeout"` SSHTimeout duration.Duration `toml:"ssh_timeout"`
// yanic socket // yanic socket

View File

@ -13,16 +13,22 @@ import (
type Node struct { type Node struct {
Lastseen jsontime.Time `json:"lastseen" mapstructure:"-"` Lastseen jsontime.Time `json:"lastseen" mapstructure:"-"`
NodeID string `json:"node_id" gorm:"primary_key" mapstructure:"node_id"` NodeID string `json:"node_id" gorm:"primary_key" mapstructure:"node_id"`
Blacklist bool `json:"blacklist"`
Address string `json:"ip"`
Hostname string `json:"hostname"` Hostname string `json:"hostname"`
Location yanicData.Location `json:"location" gorm:"embedded;embedded_prefix:location_"` HostnameRespondd string `json:"hostname_Respondd" gorm:"-"`
Wireless yanicData.Wireless `json:"wireless" gorm:"embedded;embedded_prefix:wireless_"`
Owner string `json:"owner"` Owner string `json:"owner"`
Blacklist bool `json:"blacklist" gorm:"-" mapstructure:"-"` OwnerRespondd string `json:"owner_Respondd" gorm:"-"`
Address string `json:"ip" mapstructure:"-"` Location yanicData.Location `json:"location" gorm:"embedded;embedded_prefix:location_"`
Stats struct { LocationRespondd yanicData.Location `json:"location_Respondd" gorm:"-"`
Wireless yanicData.Wireless `json:"wireless" gorm:"embedded;embedded_prefix:wireless_"`
WirelessRespondd yanicData.Wireless `json:"wireless_Respondd" gorm:"-"`
StatisticsRespondd struct {
Wireless yanicData.WirelessStatistics `json:"wireless"` Wireless yanicData.WirelessStatistics `json:"wireless"`
Clients yanicData.Clients `json:"clients"` Clients yanicData.Clients `json:"clients"`
} `json:"statistics" mapstructure:"-"` } `json:"statistics_respondd" mapstructure:"-"`
} }
func NewNode(nodeOrigin *yanicRuntime.Node, ipPrefix string) *Node { func NewNode(nodeOrigin *yanicRuntime.Node, ipPrefix string) *Node {
@ -31,15 +37,6 @@ func NewNode(nodeOrigin *yanicRuntime.Node, ipPrefix string) *Node {
Hostname: nodeinfo.Hostname, Hostname: nodeinfo.Hostname,
NodeID: nodeinfo.NodeID, NodeID: nodeinfo.NodeID,
} }
for _, ip := range nodeinfo.Network.Addresses {
if !strings.HasPrefix(ip, ipPrefix) {
continue
}
ipAddr := net.ParseIP(ip)
if node.Address == "" || ipAddr.IsGlobalUnicast() {
node.Address = ipAddr.String()
}
}
if owner := nodeinfo.Owner; owner != nil { if owner := nodeinfo.Owner; owner != nil {
node.Owner = owner.Contact node.Owner = owner.Contact
} }
@ -49,10 +46,7 @@ func NewNode(nodeOrigin *yanicRuntime.Node, ipPrefix string) *Node {
if wireless := nodeinfo.Wireless; wireless != nil { if wireless := nodeinfo.Wireless; wireless != nil {
node.Wireless = *wireless node.Wireless = *wireless
} }
if stats := nodeOrigin.Statistics; stats != nil { node.Update(nodeOrigin, ipPrefix)
node.Stats.Clients = stats.Clients
node.Stats.Wireless = stats.Wireless
}
return node return node
} }
return nil return nil
@ -60,42 +54,49 @@ func NewNode(nodeOrigin *yanicRuntime.Node, ipPrefix string) *Node {
func (n *Node) GetAddress() net.TCPAddr { func (n *Node) GetAddress() net.TCPAddr {
return net.TCPAddr{IP: net.ParseIP(n.Address), Port: 22} return net.TCPAddr{IP: net.ParseIP(n.Address), Port: 22}
} }
func (n *Node) Update(node *yanicRuntime.Node) { func (n *Node) Update(node *yanicRuntime.Node, ipPrefix string) {
if node == nil {
return
}
if nodeinfo := node.Nodeinfo; nodeinfo != nil { if nodeinfo := node.Nodeinfo; nodeinfo != nil {
n.Hostname = nodeinfo.Hostname n.HostnameRespondd = nodeinfo.Hostname
n.NodeID = nodeinfo.NodeID
n.Address = node.Address.IP.String() for _, ip := range nodeinfo.Network.Addresses {
if !strings.HasPrefix(ip, ipPrefix) {
continue
}
ipAddr := net.ParseIP(ip)
if n.Address == "" || ipAddr.IsGlobalUnicast() || !ipAddr.IsLinkLocalUnicast() {
n.Address = ip
}
}
if owner := nodeinfo.Owner; owner != nil { if owner := nodeinfo.Owner; owner != nil {
n.Owner = owner.Contact n.OwnerRespondd = owner.Contact
} }
if location := nodeinfo.Location; location != nil { if location := nodeinfo.Location; location != nil {
n.Location = *location n.LocationRespondd = *location
} }
if wireless := nodeinfo.Wireless; wireless != nil { if wireless := nodeinfo.Wireless; wireless != nil {
n.Wireless = *wireless n.WirelessRespondd = *wireless
} }
} }
if stats := node.Statistics; stats != nil {
n.StatisticsRespondd.Clients = stats.Clients
n.StatisticsRespondd.Wireless = stats.Wireless
} }
func (n *Node) IsEqual(node *Node) bool { }
if n.NodeID != node.NodeID { func (n *Node) CheckRespondd() bool {
if n.Hostname != n.HostnameRespondd {
return false return false
} }
/* if n.Owner != n.OwnerRespondd {
if n.Address != node.Address {
return false return false
} }
*/ if !locationEqual(n.Location, n.LocationRespondd) {
if n.Hostname != node.Hostname {
return false return false
} }
if n.Owner != node.Owner { if !wirelessEqual(n.Wireless, n.WirelessRespondd) {
return false
}
if !locationEqual(n.Location, node.Location) {
return false
}
if !wirelessEqual(n.Wireless, node.Wireless) {
return false return false
} }
return true return true

View File

@ -9,26 +9,26 @@ import (
"github.com/FreifunkBremen/freifunkmanager/ssh" "github.com/FreifunkBremen/freifunkmanager/ssh"
) )
func (n *Node) SSHUpdate(sshmgmt *ssh.Manager, oldnode *Node) { func (n *Node) SSHUpdate(sshmgmt *ssh.Manager) {
client, err := sshmgmt.ConnectTo(n.GetAddress()) client, err := sshmgmt.ConnectTo(n.GetAddress())
if err != nil { if err != nil {
return return
} }
defer client.Close() defer client.Close()
if oldnode == nil || n.Hostname != oldnode.Hostname { if n.Hostname != n.HostnameRespondd {
ssh.Execute(n.Address, client, fmt.Sprintf(` ssh.Execute(n.Address, client, fmt.Sprintf(`
uci set system.@system[0].hostname='%s'; uci set system.@system[0].hostname='%s';
uci commit; echo $(uci get system.@system[0].hostname) > /proc/sys/kernel/hostname;`, uci commit; echo $(uci get system.@system[0].hostname) > /proc/sys/kernel/hostname;`,
n.Hostname)) n.Hostname))
} }
if oldnode == nil || n.Owner != oldnode.Owner { if n.Owner != n.OwnerRespondd {
ssh.Execute(n.Address, client, fmt.Sprintf(` ssh.Execute(n.Address, client, fmt.Sprintf(`
uci set gluon-node-info.@owner[0].contact='%s'; uci set gluon-node-info.@owner[0].contact='%s';
uci commit gluon-node-info;`, uci commit gluon-node-info;`,
n.Owner)) n.Owner))
} }
if oldnode == nil || !locationEqual(n.Location, oldnode.Location) { if !locationEqual(n.Location, n.LocationRespondd) {
ssh.Execute(n.Address, client, fmt.Sprintf(` ssh.Execute(n.Address, client, fmt.Sprintf(`
uci set gluon-node-info.@location[0].latitude='%f'; uci set gluon-node-info.@location[0].latitude='%f';
uci set gluon-node-info.@location[0].longitude='%f'; uci set gluon-node-info.@location[0].longitude='%f';
@ -58,14 +58,14 @@ func (n *Node) SSHUpdate(sshmgmt *ssh.Manager, oldnode *Node) {
radio := ssh.SSHResultToString(result) radio := ssh.SSHResultToString(result)
ch := GetChannel(n.Wireless.Channel24) ch := GetChannel(n.Wireless.Channel24)
if radio != "" && ch != nil { if radio != "" && ch != nil {
if oldnode == nil || n.Wireless.TxPower24 != oldnode.Wireless.TxPower24 { if n.Wireless.TxPower24 != n.WirelessRespondd.TxPower24 {
ssh.Execute(n.Address, client, fmt.Sprintf(` ssh.Execute(n.Address, client, fmt.Sprintf(`
uci set wireless.%s.txpower='%d'; uci set wireless.%s.txpower='%d';
uci commit wireless;`, uci commit wireless;`,
radio, n.Wireless.TxPower24)) radio, n.Wireless.TxPower24))
runWifi = true runWifi = true
} }
if oldnode == nil || n.Wireless.Channel24 != oldnode.Wireless.Channel24 { if n.Wireless.Channel24 != n.WirelessRespondd.Channel24 {
ssh.Execute(n.Address, client, fmt.Sprintf(` ssh.Execute(n.Address, client, fmt.Sprintf(`
ubus call hostapd.%s switch_chan '{"freq":%d}' ubus call hostapd.%s switch_chan '{"freq":%d}'
uci set wireless.%s.channel='%d'; uci set wireless.%s.channel='%d';
@ -87,14 +87,14 @@ func (n *Node) SSHUpdate(sshmgmt *ssh.Manager, oldnode *Node) {
radio = ssh.SSHResultToString(result) radio = ssh.SSHResultToString(result)
ch = GetChannel(n.Wireless.Channel5) ch = GetChannel(n.Wireless.Channel5)
if radio != "" && ch != nil { if radio != "" && ch != nil {
if oldnode == nil || n.Wireless.TxPower5 != oldnode.Wireless.TxPower5 { if n.Wireless.TxPower5 != n.WirelessRespondd.TxPower5 {
ssh.Execute(n.Address, client, fmt.Sprintf(` ssh.Execute(n.Address, client, fmt.Sprintf(`
uci set wireless.%s.txpower='%d'; uci set wireless.%s.txpower='%d';
uci commit wireless;`, uci commit wireless;`,
radio, n.Wireless.TxPower5)) radio, n.Wireless.TxPower5))
runWifi = true runWifi = true
} }
if oldnode == nil || n.Wireless.Channel5 != oldnode.Wireless.Channel5 { if n.Wireless.Channel5 != n.WirelessRespondd.Channel5 {
ssh.Execute(n.Address, client, fmt.Sprintf(` ssh.Execute(n.Address, client, fmt.Sprintf(`
ubus call hostapd.%s switch_chan '{"freq":%d}' ubus call hostapd.%s switch_chan '{"freq":%d}'
uci set wireless.%s.channel='%d'; uci set wireless.%s.channel='%d';
@ -103,6 +103,4 @@ func (n *Node) SSHUpdate(sshmgmt *ssh.Manager, oldnode *Node) {
radio, n.Wireless.Channel5)) radio, n.Wireless.Channel5))
} }
} }
oldnode = n
} }

View File

@ -27,10 +27,9 @@ func TestNode(t *testing.T) {
assert.NotNil(n1) assert.NotNil(n1)
assert.Equal(float64(13), n1.Location.Altitude) assert.Equal(float64(13), n1.Location.Altitude)
n2 := NewNode(node1, "") assert.True(n1.CheckRespondd())
assert.True(n2.IsEqual(n1))
node1.Nodeinfo.Owner.Contact = "blub2" node1.Nodeinfo.Owner.Contact = "blub2"
n2.Update(node1) n1.Update(node1, "")
assert.False(n2.IsEqual(n1)) assert.False(n1.CheckRespondd())
} }

View File

@ -17,12 +17,12 @@ type YanicDB struct {
databaseYanic.Connection databaseYanic.Connection
db *gorm.DB db *gorm.DB
ssh *ssh.Manager ssh *ssh.Manager
sendNode func(*Node, bool) sendNode func(*Node)
sendStats func(*runtimeYanic.GlobalStats) sendStats func(*runtimeYanic.GlobalStats)
prefix string prefix string
} }
func NewYanicDB(db *gorm.DB, ssh *ssh.Manager, sendNode func(*Node, bool), sendStats func(*runtimeYanic.GlobalStats), prefix string) *YanicDB { func NewYanicDB(db *gorm.DB, ssh *ssh.Manager, sendNode func(*Node), sendStats func(*runtimeYanic.GlobalStats), prefix string) *YanicDB {
return &YanicDB{ return &YanicDB{
db: db, db: db,
ssh: ssh, ssh: ssh,
@ -33,45 +33,52 @@ func NewYanicDB(db *gorm.DB, ssh *ssh.Manager, sendNode func(*Node, bool), sendS
} }
func (conn *YanicDB) InsertNode(n *runtimeYanic.Node) { func (conn *YanicDB) InsertNode(n *runtimeYanic.Node) {
node := NewNode(n, conn.prefix) nodeid := ""
if node == nil { if nodeinfo := n.Nodeinfo; nodeinfo != nil {
nodeid = nodeinfo.NodeID
} else {
return return
} }
node.Lastseen = jsontime.Now() logger := log.WithField("method", "LearnNode").WithField("node_id", nodeid)
logger := log.WithField("method", "LearnNode").WithField("node_id", node.NodeID)
lNode := Node{ lNode := Node{
NodeID: node.NodeID, NodeID: nodeid,
} }
if conn.db.First(&lNode).Error == nil { if conn.db.First(&lNode).Error == nil {
lNode.Update(n, conn.prefix)
conn.db.Model(&lNode).Update(map[string]interface{}{ conn.db.Model(&lNode).Update(map[string]interface{}{
"Lastseen": jsontime.Now(), "Lastseen": jsontime.Now(),
//"StatsWireless": node.StatsWireless, //"StatsWireless": node.StatsWireless,
//"StatsClients": node.StatsClients, //"StatsClients": node.StatsClients,
"Address": node.Address, "Address": lNode.Address,
}) })
if lNode.Blacklist { if lNode.Blacklist {
logger.Debug("on blacklist") logger.Debug("on blacklist")
return return
} }
conn.sendNode(node, false) conn.sendNode(&lNode)
if !node.IsEqual(&lNode) { if !lNode.CheckRespondd() {
lNode.SSHUpdate(conn.ssh, node) lNode.SSHUpdate(conn.ssh)
logger.Debug("yanic trigger sshupdate again") logger.Debug("yanic trigger sshupdate again")
} else { } else {
logger.Debug("yanic update") logger.Debug("yanic update")
} }
return return
} }
node := NewNode(n, conn.prefix)
if node == nil {
return
}
node.Lastseen = jsontime.Now() node.Lastseen = jsontime.Now()
_, err := conn.ssh.RunOn(node.GetAddress(), "uptime") _, err := conn.ssh.RunOn(node.GetAddress(), "uptime")
if err != nil { if err != nil {
logger.Debug("set on blacklist") logger.Debugf("set on blacklist: %s", err.Error())
node.Blacklist = true node.Blacklist = true
} }
conn.db.Create(&node) conn.db.Create(&node)
conn.sendNode(node, true) if !node.Blacklist {
conn.sendNode(node)
}
} }
func (conn *YanicDB) InsertLink(link *runtimeYanic.Link, time time.Time) { func (conn *YanicDB) InsertLink(link *runtimeYanic.Link, time time.Time) {

View File

@ -13,7 +13,7 @@ func TestExecute(t *testing.T) {
addr := net.TCPAddr{IP: net.ParseIP("fd2f:5119:f2c::127"), Port: 22} addr := net.TCPAddr{IP: net.ParseIP("fd2f:5119:f2c::127"), Port: 22}
mgmt := NewManager("~/.ssh/id_rsa", time.Second) mgmt := NewManager("~/.ssh/id_rsa", 5*time.Second)
assert.NotNil(mgmt, "no new manager created") assert.NotNil(mgmt, "no new manager created")
client, err := mgmt.ConnectTo(addr) client, err := mgmt.ConnectTo(addr)

View File

@ -11,9 +11,12 @@ import (
func TestManager(t *testing.T) { func TestManager(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
mgmt := NewManager("~/.ssh/id_rsa", time.Second) mgmt := NewManager("~/.ssh/id_rsa", 5*time.Second)
assert.NotNil(mgmt, "no new manager created") assert.NotNil(mgmt, "no new manager created")
client, _ := mgmt.ConnectTo(net.TCPAddr{IP: net.ParseIP("fd2f:5119:f2c::127"), Port: 22}) client, _ := mgmt.ConnectTo(net.TCPAddr{IP: net.ParseIP("fd2f:5119:f2c::127"), Port: 22})
assert.NotNil(client, "no connection to client")
if client == nil {
client.Close() client.Close()
} }
}

View File

@ -12,7 +12,7 @@ import (
func TestRun(t *testing.T) { func TestRun(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
addr := net.TCPAddr{IP: net.ParseIP("fd2f:5119:f2c::127"), Port: 22} addr := net.TCPAddr{IP: net.ParseIP("fd2f:5119:f2c::127"), Port: 22}
mgmt := NewManager("~/.ssh/id_rsa", time.Second) mgmt := NewManager("~/.ssh/id_rsa", 5*time.Second)
assert.NotNil(mgmt, "no new manager created") assert.NotNil(mgmt, "no new manager created")
client, err := mgmt.ConnectTo(addr) client, err := mgmt.ConnectTo(addr)

View File

@ -162,7 +162,7 @@ export function delEvent (to, func) {
} }
export function sendnode(node, callback) { export function sendnode(node, callback) {
sendjson({'subject':'node-system','body': node}, (msg) => { sendjson({'subject':'node','body': node}, (msg) => {
if(!msg.body) { if(!msg.body) {
notify.send({ notify.send({
'header': 'Speichern', 'header': 'Speichern',
@ -190,10 +190,7 @@ setEvent('auth_status', (msg) => {
render(); render();
}); });
addEvent('node-system', (msg) => { addEvent('node', (msg) => {
store.updateNode(msg.body, true);
});
addEvent('node-current', (msg) => {
store.updateNode(msg.body); store.updateNode(msg.body);
}); });
addEvent('channels_wifi24', (msg) => { addEvent('channels_wifi24', (msg) => {

View File

@ -10,14 +10,7 @@ export function getNode (nodeid) {
} }
let node = list[nodeid]; let node = list[nodeid];
if (current[nodeid]) { // keep structur for pings later
const cNode = current[nodeid];
// eslint-disable-next-line no-underscore-dangle
node._wireless = cNode.wireless;
node.lastseen = cNode.lastseen;
node.statistics = cNode.statistics;
}
return node; return node;
}; };
@ -38,12 +31,8 @@ export function createNode (nodeid) {
// Overwrites the values for the specified node (identified by its node_id) with new values. // Overwrites the values for the specified node (identified by its node_id) with new values.
// If system==false, the special "current" node will be modified instead. // If system==false, the special "current" node will be modified instead.
export function updateNode (node, system) { export function updateNode (node) {
if (system) {
list[node.node_id] = node; list[node.node_id] = node;
} else {
current[node.node_id] = node;
}
}; };
// Returns a list of all known nodes. // Returns a list of all known nodes.

View File

@ -45,7 +45,7 @@ export class ListView extends View {
{ name:'Freq' }, { name:'Freq' },
{ {
name:'CurCh', name:'CurCh',
sort: (a, b) => (a._wireless ? a._wireless.channel24 : 0) - (b._wireless ? b._wireless.channel24 : 0), sort: (a, b) => (a.wireless_respondd ? a.wireless_respondd.channel24 : 0) - (b.wireless_respondd ? b.wireless_respondd.channel24 : 0),
reverse: false reverse: false
}, },
{ {
@ -55,7 +55,7 @@ export class ListView extends View {
}, },
{ {
name:'CurPW', name:'CurPW',
sort: (a, b) => (a._wireless ? a._wireless.txpower24 : 0) - (b._wireless ? b._wireless.txpower24 : 0), sort: (a, b) => (a.wireless_respondd ? a.wireless_respondd.txpower24 : 0) - (b.wireless_respondd ? b.wireless_respondd.txpower24 : 0),
reverse: false reverse: false
}, },
{ {
@ -65,12 +65,12 @@ export class ListView extends View {
}, },
{ {
name:'Clients', name:'Clients',
sort: (a, b) => a.statistics.clients.wifi24 - b.statistics.clients.wifi24, sort: (a, b) => a.statistics_respondd.clients.wifi24 - b.statistics_respondd.clients.wifi24,
reverse: false reverse: false
}, },
{ {
name:'ChanUtil', name:'ChanUtil',
sort: (a, b) => (a.statistics.wireless ? a.statistics.wireless.filter((d) => d.frequency < 5000)[0].ChanUtil || 0 : 0) - (b.statistics.wireless ? b.statistics.wireless.filter((d) => d.frequency < 5000)[0].ChanUtil || 0 : 0), sort: (a, b) => (a.statistics_respondd.wireless ? a.statistics_respondd.wireless.filter((d) => d.frequency < 5000)[0].ChanUtil || 0 : 0) - (b.statistics_respondd.wireless ? b.statistics_respondd.wireless.filter((d) => d.frequency < 5000)[0].ChanUtil || 0 : 0),
reverse: false reverse: false
}, },
{ name:'Options' } { name:'Options' }
@ -101,7 +101,7 @@ export class ListView extends View {
return V.h('tr', {},[ return V.h('tr', {},[
V.h('td', { V.h('td', {
'class':(new Date(node.lastseen) < startdate)?'offline':(!node._wireless)?'unseen':'' 'class':(new Date(node.lastseen) < startdate)?'offline':(!node.wireless_respondd)?'unseen':''
}, FromNowAgo(node.lastseen)), }, FromNowAgo(node.lastseen)),
V.h('td', {}, node.node_id), V.h('td', {}, node.node_id),
V.h('td', {}, V.h('input',{ V.h('td', {}, V.h('input',{
@ -127,8 +127,8 @@ export class ListView extends View {
V.h('span', {},'5 GHz') V.h('span', {},'5 GHz')
]), ]),
V.h('td', {}, [ V.h('td', {}, [
V.h('span', {}, node._wireless ? node._wireless.channel24 || '-':'-'), V.h('span', {}, node.wireless_respondd ? node.wireless_respondd.channel24 || '-':'-'),
V.h('span', {}, node._wireless ? node._wireless.channel5 || '-':'-') V.h('span', {}, node.wireless_respondd ? node.wireless_respondd.channel5 || '-':'-')
]), ]),
V.h('td', {}, [ V.h('td', {}, [
V.h('span', {}, V.h('select',{ V.h('span', {}, V.h('select',{
@ -157,8 +157,8 @@ export class ListView extends View {
}, channel5Options)) }, channel5Options))
]), ]),
V.h('td', {}, [ V.h('td', {}, [
V.h('span', {}, node._wireless ? node._wireless.txpower24 || '-':'-'), V.h('span', {}, node.wireless_respondd ? node.wireless_respondd.txpower24 || '-':'-'),
V.h('span', {}, node._wireless ? node._wireless.txpower5 || '-':'-') V.h('span', {}, node.wireless_respondd ? node.wireless_respondd.txpower5 || '-':'-')
]), ]),
V.h('td', {}, [ V.h('td', {}, [
V.h('span', {}, V.h('input',{ V.h('span', {}, V.h('input',{
@ -205,12 +205,12 @@ export class ListView extends View {
})) }))
]), ]),
V.h('td', {}, [ V.h('td', {}, [
V.h('span', {}, node.statistics.clients.wifi24), V.h('span', {}, node.statistics_respondd.clients.wifi24),
V.h('span', {}, node.statistics.clients.wifi5) V.h('span', {}, node.statistics_respondd.clients.wifi5)
]), ]),
V.h('td', {}, [ V.h('td', {}, [
V.h('span', {}, node.statistics.wireless ? (node.statistics.wireless.filter((d) => d.frequency < 5000)[0] || {ChanUtil: '-'}).ChanUtil : '-'), V.h('span', {}, node.statistics_respondd.wireless ? (node.statistics_respondd.wireless.filter((d) => d.frequency < 5000)[0] || {ChanUtil: '-'}).ChanUtil : '-'),
V.h('span', {}, node.statistics.wireless ? (node.statistics.wireless.filter((d) => d.frequency > 5000)[0] || {ChanUtil: '-'}).ChanUtil : '-'), V.h('span', {}, node.statistics_respondd.wireless ? (node.statistics_respondd.wireless.filter((d) => d.frequency > 5000)[0] || {ChanUtil: '-'}).ChanUtil : '-'),
]), ]),
V.h('td', {}, [ V.h('td', {}, [
V.h('a',{ V.h('a',{

View File

@ -108,9 +108,9 @@ export class MapView extends View {
} }
if (node.statistics && node.statistics.clients) { if (node.statistics_respondd && node.statistics_respondd.clients) {
// eslint-disable-next-line prefer-destructuring // eslint-disable-next-line prefer-destructuring
wifi24 = node.statistics.clients.wifi24; wifi24 = node.statistics_respondd.clients.wifi24;
if (wifi24 < config.map.icon.warn.wifi24 && wifi24 > 0) { if (wifi24 < config.map.icon.warn.wifi24 && wifi24 > 0) {
className += ' client24'; className += ' client24';
@ -120,7 +120,7 @@ export class MapView extends View {
className += ' client24-crit'; className += ' client24-crit';
} }
// eslint-disable-next-line prefer-destructuring // eslint-disable-next-line prefer-destructuring
wifi5 = node.statistics.clients.wifi5; wifi5 = node.statistics_respondd.clients.wifi5;
if (wifi5 < config.map.icon.warn.wifi5 && wifi5 > 0) { if (wifi5 < config.map.icon.warn.wifi5 && wifi5 > 0) {
className += ' client5'; className += ' client5';
@ -182,13 +182,13 @@ export class MapView extends View {
this.clientLayer24.setData(nodes.filter((node) => { this.clientLayer24.setData(nodes.filter((node) => {
return (node.location && node.location.latitude && node.location.longitude); return (node.location && node.location.latitude && node.location.longitude);
}).map((node) => { }).map((node) => {
return [node.location.latitude, node.location.longitude, node.statistics.clients.wifi24 || 0]; return [node.location.latitude, node.location.longitude, node.statistics_respondd.clients.wifi24 || 0];
})); }));
this.clientLayer5.setData(nodes.filter((node) => { this.clientLayer5.setData(nodes.filter((node) => {
return (node.location && node.location.latitude && node.location.longitude); return (node.location && node.location.latitude && node.location.longitude);
}).map((node) => { }).map((node) => {
return [node.location.latitude, node.location.longitude, node.statistics.clients.wifi5 || 0]; return [node.location.latitude, node.location.longitude, node.statistics_respondd.clients.wifi5 || 0];
})); }));
this.map.invalidateSize(); this.map.invalidateSize();
} }

View File

@ -52,7 +52,7 @@ export class StatisticsView extends View {
this.clientsWifi5.innerHTML = msg.body.ClientsWifi5; this.clientsWifi5.innerHTML = msg.body.ClientsWifi5;
} }
}); });
socket.addEvent('node-current', this.updateChannelTable.bind(this)); socket.addEvent('node', this.updateChannelTable.bind(this));
socket.addEvent('channels_wifi24', this.updateChannelTable.bind(this)); socket.addEvent('channels_wifi24', this.updateChannelTable.bind(this));
socket.addEvent('channels_wifi5', this.updateChannelTable.bind(this)); socket.addEvent('channels_wifi5', this.updateChannelTable.bind(this));
} }

View File

@ -16,23 +16,17 @@ func (ws *WebsocketServer) connectHandler(logger *log.Entry, msg *wsLib.Message)
var nodes []*runtime.Node var nodes []*runtime.Node
var count int var count int
ws.db.Find(&nodes).Count(&count) ws.db.Where("blacklist = false").Find(&nodes).Count(&count)
ws.nodes.Lock() ws.nodes.Lock()
i := 0 i := 0
for _, node := range ws.nodes.List { for _, node := range nodes {
n := runtime.NewNode(node, "") //TODO skip blacklist
if n == nil { node.Update(ws.nodes.List[node.NodeID], ws.ipPrefix)
continue msg.From.Write(&wsLib.Message{Subject: MessageTypeNode, Body: node})
}
n.Lastseen = node.Lastseen
msg.From.Write(&wsLib.Message{Subject: MessageTypeCurrentNode, Body: n})
i++ i++
} }
ws.nodes.Unlock() ws.nodes.Unlock()
for _, node := range nodes {
msg.From.Write(&wsLib.Message{Subject: MessageTypeSystemNode, Body: node})
}
msg.From.Write(&wsLib.Message{Subject: MessageTypeChannelsWifi24, Body: wifi24Channels}) msg.From.Write(&wsLib.Message{Subject: MessageTypeChannelsWifi24, Body: wifi24Channels})
msg.From.Write(&wsLib.Message{Subject: MessageTypeChannelsWifi5, Body: wifi5Channels}) msg.From.Write(&wsLib.Message{Subject: MessageTypeChannelsWifi5, Body: wifi5Channels})
logger.Debugf("done - fetch %d nodes and send %d", count, i) logger.Debugf("done - fetch %d nodes and send %d", count, i)

View File

@ -1,14 +1,6 @@
package websocket package websocket
import ( /*
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/FreifunkBremen/freifunkmanager/runtime"
)
func TestConnectChannelInit(t *testing.T) { func TestConnectChannelInit(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
@ -25,3 +17,4 @@ func TestConnectChannelInit(t *testing.T) {
assert.Len(wifi5Channels, 35) assert.Len(wifi5Channels, 35)
} }
*/

View File

@ -50,7 +50,11 @@ func (ws *WebsocketServer) nodeHandler(logger *log.Entry, msg *wsLib.Message) er
logger.Warnf("could not change %s: %s", node.NodeID, err.Error.Error()) logger.Warnf("could not change %s: %s", node.NodeID, err.Error.Error())
return err.Error return err.Error
} }
ws.SendNode(&node, true) ws.nodes.Lock()
nodeRespondd := ws.nodes.List[node.NodeID]
ws.nodes.Unlock()
node.Update(nodeRespondd, ws.ipPrefix)
ws.SendNode(&node)
logger.Infof("change %s", node.NodeID) logger.Infof("change %s", node.NodeID)
return nil return nil
} }

View File

@ -10,7 +10,6 @@ const (
MessageTypeChannelsWifi24 = "channels_wifi24" MessageTypeChannelsWifi24 = "channels_wifi24"
MessageTypeChannelsWifi5 = "channels_wifi5" MessageTypeChannelsWifi5 = "channels_wifi5"
MessageTypeSystemNode = "node-system" MessageTypeNode = "node"
MessageTypeCurrentNode = "node-current"
MessageTypeStats = "stats" MessageTypeStats = "stats"
) )

View File

@ -8,12 +8,8 @@ import (
"github.com/FreifunkBremen/freifunkmanager/runtime" "github.com/FreifunkBremen/freifunkmanager/runtime"
) )
func (ws *WebsocketServer) SendNode(node *runtime.Node, system bool) { func (ws *WebsocketServer) SendNode(node *runtime.Node) {
msgType := MessageTypeCurrentNode ws.ws.SendAll(&wsLib.Message{Subject: MessageTypeNode, Body: node})
if system {
msgType = MessageTypeSystemNode
}
ws.ws.SendAll(&wsLib.Message{Subject: msgType, Body: node})
} }
func (ws *WebsocketServer) SendStats(data *yanicRuntime.GlobalStats) { func (ws *WebsocketServer) SendStats(data *yanicRuntime.GlobalStats) {

View File

@ -4,7 +4,6 @@ import (
"net/http" "net/http"
wsLib "dev.sum7.eu/genofire/golang-lib/websocket" wsLib "dev.sum7.eu/genofire/golang-lib/websocket"
"github.com/google/uuid"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"github.com/FreifunkBremen/yanic/runtime" "github.com/FreifunkBremen/yanic/runtime"
@ -14,21 +13,21 @@ type WebsocketServer struct {
nodes *runtime.Nodes nodes *runtime.Nodes
db *gorm.DB db *gorm.DB
secret string secret string
loggedIn map[uuid.UUID]bool ipPrefix string
inputMSG chan *wsLib.Message inputMSG chan *wsLib.Message
ws *wsLib.Server ws *wsLib.Server
handlers map[string]WebsocketHandlerFunc handlers map[string]WebsocketHandlerFunc
} }
func NewWebsocketServer(secret string, db *gorm.DB, nodes *runtime.Nodes) *WebsocketServer { func NewWebsocketServer(secret string, ipPrefix string, db *gorm.DB, nodes *runtime.Nodes) *WebsocketServer {
ownWS := WebsocketServer{ ownWS := WebsocketServer{
nodes: nodes, nodes: nodes,
db: db, db: db,
handlers: make(map[string]WebsocketHandlerFunc), handlers: make(map[string]WebsocketHandlerFunc),
loggedIn: make(map[uuid.UUID]bool),
inputMSG: make(chan *wsLib.Message), inputMSG: make(chan *wsLib.Message),
secret: secret, secret: secret,
ipPrefix: ipPrefix,
} }
ownWS.ws = wsLib.NewServer(ownWS.inputMSG, wsLib.NewSessionManager()) ownWS.ws = wsLib.NewServer(ownWS.inputMSG, wsLib.NewSessionManager())
@ -39,7 +38,7 @@ func NewWebsocketServer(secret string, db *gorm.DB, nodes *runtime.Nodes) *Webso
ownWS.handlers[MessageTypeAuthStatus] = ownWS.authStatusHandler ownWS.handlers[MessageTypeAuthStatus] = ownWS.authStatusHandler
ownWS.handlers[MessageTypeLogout] = ownWS.logoutHandler ownWS.handlers[MessageTypeLogout] = ownWS.logoutHandler
ownWS.handlers[MessageTypeSystemNode] = ownWS.nodeHandler ownWS.handlers[MessageTypeNode] = ownWS.nodeHandler
http.HandleFunc("/ws", ownWS.ws.Handler) http.HandleFunc("/ws", ownWS.ws.Handler)
go ownWS.MessageHandler() go ownWS.MessageHandler()