remove lldp

This commit is contained in:
Siyuan Miao 2025-09-24 21:05:05 +00:00 committed by Siyuan
parent 9db23f28db
commit d0df8eaa44
16 changed files with 1004 additions and 702 deletions

View File

@ -1,84 +0,0 @@
package lldp
import (
"fmt"
"net"
"os"
"syscall"
"unsafe"
"github.com/google/gopacket/afpacket"
"golang.org/x/sys/unix"
)
const (
afPacketBufferSize = 2 // in MiB
afPacketSnaplen = 9216
)
func afPacketComputeSize(targetSizeMb int, snaplen int, pageSize int) (
frameSize int, blockSize int, numBlocks int, err error) {
if snaplen < pageSize {
frameSize = pageSize / (pageSize / snaplen)
} else {
frameSize = (snaplen/pageSize + 1) * pageSize
}
// 128 is the default from the gopacket library so just use that
blockSize = frameSize * 128
numBlocks = (targetSizeMb * 1024 * 1024) / blockSize
if numBlocks == 0 {
return 0, 0, 0, fmt.Errorf("interface buffersize is too small")
}
return frameSize, blockSize, numBlocks, nil
}
func afPacketNewTPacket(ifName string) (*afpacket.TPacket, error) {
szFrame, szBlock, numBlocks, err := afPacketComputeSize(
afPacketBufferSize,
afPacketSnaplen,
os.Getpagesize())
if err != nil {
return nil, err
}
return afpacket.NewTPacket(
afpacket.OptInterface(ifName),
afpacket.OptFrameSize(szFrame),
afpacket.OptBlockSize(szBlock),
afpacket.OptNumBlocks(numBlocks),
afpacket.OptAddVLANHeader(false),
afpacket.SocketRaw,
afpacket.TPacketVersion3)
}
type ifreq struct {
ifrName [IFNAMSIZ]byte
ifrHwaddr syscall.RawSockaddr
}
func addMulticastAddr(ifName string, addr net.HardwareAddr) error {
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0)
if err != nil {
return err
}
defer syscall.Close(fd)
var name [IFNAMSIZ]byte
copy(name[:], []byte(ifName))
ifr := &ifreq{
ifrName: name,
ifrHwaddr: toRawSockaddr(addr),
}
_, _, ep := unix.Syscall(unix.SYS_IOCTL, uintptr(fd),
unix.SIOCADDMULTI, uintptr(unsafe.Pointer(ifr)))
if ep != 0 {
return syscall.Errno(ep)
}
return nil
}

View File

@ -1,15 +0,0 @@
//go:build arm && linux
package lldp
import (
"net"
"syscall"
)
func toRawSockaddr(mac net.HardwareAddr) (sockaddr syscall.RawSockaddr) {
for i, n := range mac {
sockaddr.Data[i] = uint8(n)
}
return
}

View File

@ -1,15 +0,0 @@
//go:build !arm && linux
package lldp
import (
"net"
"syscall"
)
func toRawSockaddr(mac net.HardwareAddr) (sockaddr syscall.RawSockaddr) {
for i, n := range mac {
sockaddr.Data[i] = int8(n)
}
return
}

View File

@ -1,106 +0,0 @@
package lldp
import (
"context"
"sync"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/afpacket"
"github.com/jellydator/ttlcache/v3"
"github.com/jetkvm/kvm/internal/logging"
"github.com/rs/zerolog"
)
var defaultLogger = logging.GetSubsystemLogger("lldp")
type LLDP struct {
l *zerolog.Logger
tPacket *afpacket.TPacket
pktSource *gopacket.PacketSource
rxCtx context.Context
rxCancel context.CancelFunc
rxLock sync.Mutex
enableRx bool
enableTx bool
packets chan gopacket.Packet
interfaceName string
stop chan struct{}
neighbors *ttlcache.Cache[string, Neighbor]
}
type LLDPOptions struct {
InterfaceName string
EnableRx bool
EnableTx bool
Logger *zerolog.Logger
}
func NewLLDP(opts *LLDPOptions) *LLDP {
if opts.Logger == nil {
opts.Logger = defaultLogger
}
if opts.InterfaceName == "" {
opts.Logger.Fatal().Msg("InterfaceName is required")
}
return &LLDP{
interfaceName: opts.InterfaceName,
enableRx: opts.EnableRx,
enableTx: opts.EnableTx,
l: opts.Logger,
neighbors: ttlcache.New(ttlcache.WithTTL[string, Neighbor](1 * time.Hour)),
}
}
func (l *LLDP) Start() error {
l.rxLock.Lock()
defer l.rxLock.Unlock()
if l.rxCtx != nil {
l.l.Info().Msg("LLDP already started")
return nil
}
l.rxCtx, l.rxCancel = context.WithCancel(context.Background())
if l.enableRx {
l.l.Info().Msg("setting up AF_PACKET")
if err := l.setUpCapture(); err != nil {
l.l.Error().Err(err).Msg("unable to set up AF_PACKET")
return err
}
if err := l.startCapture(); err != nil {
l.l.Error().Err(err).Msg("unable to start capture")
return err
}
}
go l.neighbors.Start()
return nil
}
func (l *LLDP) Stop() error {
l.rxLock.Lock()
defer l.rxLock.Unlock()
if l.rxCancel != nil {
l.rxCancel()
l.rxCancel = nil
l.rxCtx = nil
}
if l.enableRx {
_ = l.shutdownCapture()
}
l.neighbors.Stop()
l.neighbors.DeleteAll()
return nil
}

View File

@ -1,57 +0,0 @@
package lldp
import "time"
type Neighbor struct {
Mac string `json:"mac"`
Source string `json:"source"`
ChassisID string `json:"chassis_id"`
PortID string `json:"port_id"`
PortDescription string `json:"port_description"`
SystemName string `json:"system_name"`
SystemDescription string `json:"system_description"`
TTL uint16 `json:"ttl"`
ManagementAddress string `json:"management_address"`
Values map[string]string `json:"values"`
}
func (l *LLDP) addNeighbor(mac string, neighbor Neighbor, ttl time.Duration) {
logger := l.l.With().
Str("mac", mac).
Interface("neighbor", neighbor).
Logger()
current_neigh := l.neighbors.Get(mac)
if current_neigh != nil {
current_source := current_neigh.Value().Source
if current_source == "lldp" && neighbor.Source != "lldp" {
logger.Info().Msg("skip updating neighbor, as LLDP has higher priority")
return
}
}
logger.Info().Msg("adding neighbor")
l.neighbors.Set(mac, neighbor, ttl)
}
func (l *LLDP) deleteNeighbor(mac string) {
logger := l.l.With().
Str("mac", mac).
Logger()
logger.Info().Msg("deleting neighbor")
l.neighbors.Delete(mac)
}
func (l *LLDP) GetNeighbors() []Neighbor {
items := l.neighbors.Items()
neighbors := make([]Neighbor, 0, len(items))
for _, item := range items {
neighbors = append(neighbors, item.Value())
}
l.l.Info().Interface("neighbors", neighbors).Msg("neighbors")
return neighbors
}

View File

@ -1,264 +0,0 @@
package lldp
import (
"fmt"
"net"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/rs/zerolog"
"golang.org/x/net/bpf"
)
const IFNAMSIZ = 16
var (
lldpDefaultTTL = 120 * time.Second
cdpDefaultTTL = 180 * time.Second
)
// from lldpd
// https://github.com/lldpd/lldpd/blob/9034c9332cca0c8b1a20e1287f0e5fed81f7eb2a/src/daemon/lldpd.h#L246
//
//nolint:govet
var bpfFilter = []bpf.RawInstruction{
{0x30, 0, 0, 0x00000000}, {0x54, 0, 0, 0x00000001}, {0x15, 0, 16, 0x00000001},
{0x28, 0, 0, 0x0000000c}, {0x15, 0, 6, 0x000088cc},
{0x20, 0, 0, 0x00000002}, {0x15, 2, 0, 0xc200000e},
{0x15, 1, 0, 0xc2000003}, {0x15, 0, 2, 0xc2000000},
{0x28, 0, 0, 0x00000000}, {0x15, 12, 13, 0x00000180},
{0x20, 0, 0, 0x00000002}, {0x15, 0, 2, 0x52cccccc},
{0x28, 0, 0, 0x00000000}, {0x15, 8, 9, 0x000001e0},
{0x15, 1, 0, 0x0ccccccc}, {0x15, 0, 2, 0x81000100},
{0x28, 0, 0, 0x00000000}, {0x15, 4, 5, 0x00000100},
{0x20, 0, 0, 0x00000002}, {0x15, 0, 3, 0x2b000000},
{0x28, 0, 0, 0x00000000}, {0x15, 0, 1, 0x000000e0},
{0x6, 0, 0, 0x00040000},
{0x6, 0, 0, 0x00000000},
}
var multicastAddrs = []string{
// LLDP
"01:80:C2:00:00:00",
"01:80:C2:00:00:03",
"01:80:C2:00:00:0E",
// CDP
"01:00:0C:CC:CC:CC",
}
func (l *LLDP) setUpCapture() error {
logger := l.l.With().Str("interface", l.interfaceName).Logger()
tPacket, err := afPacketNewTPacket(l.interfaceName)
if err != nil {
return err
}
logger.Info().Msg("created TPacket")
// set up multicast addresses
// otherwise the kernel might discard the packets
// another workaround would be to enable promiscuous mode but that's too tricky
for _, mac := range multicastAddrs {
hwAddr, err := net.ParseMAC(mac)
if err != nil {
logger.Error().Msgf("unable to parse MAC address %s: %s", mac, err)
continue
}
if err := addMulticastAddr(l.interfaceName, hwAddr); err != nil {
logger.Error().Msgf("unable to add multicast address %s: %s", mac, err)
continue
}
logger.Info().
Interface("hwaddr", hwAddr).
Msgf("added multicast address")
}
if err = tPacket.SetBPF(bpfFilter); err != nil {
logger.Error().Msgf("unable to set BPF filter: %s", err)
tPacket.Close()
return err
}
logger.Info().Msg("BPF filter set")
l.pktSource = gopacket.NewPacketSource(tPacket, layers.LayerTypeEthernet)
l.tPacket = tPacket
return nil
}
func (l *LLDP) startCapture() error {
logger := l.l.With().Str("interface", l.interfaceName).Logger()
if l.tPacket == nil {
return fmt.Errorf("AFPacket not initialized")
}
if l.pktSource == nil {
return fmt.Errorf("packet source not initialized")
}
go func() {
logger.Info().Msg("starting capture LLDP ethernet frames")
for {
select {
case <-l.rxCtx.Done():
logger.Info().Msg("shutting down LLDP capture")
return
case packet := <-l.pktSource.Packets():
if err := l.handlePacket(packet, &logger); err != nil {
logger.Error().Msgf("error handling packet: %s", err)
}
}
}
}()
return nil
}
func (l *LLDP) handlePacket(packet gopacket.Packet, logger *zerolog.Logger) error {
linkLayer := packet.LinkLayer()
if linkLayer == nil {
return fmt.Errorf("no link layer")
}
srcMac := linkLayer.LinkFlow().Src().String()
dstMac := linkLayer.LinkFlow().Dst().String()
logger.Trace().
Str("src_mac", srcMac).
Str("dst_mac", dstMac).
Int("length", len(packet.Data())).
Hex("data", packet.Data()).
Msg("received packet")
lldpRaw := packet.Layer(layers.LayerTypeLinkLayerDiscovery)
if lldpRaw != nil {
logger.Trace().Msgf("Found LLDP Frame")
lldpInfo := packet.Layer(layers.LayerTypeLinkLayerDiscoveryInfo)
if lldpInfo == nil {
return fmt.Errorf("no LLDP info layer")
}
return l.handlePacketLLDP(
srcMac,
lldpRaw.(*layers.LinkLayerDiscovery),
lldpInfo.(*layers.LinkLayerDiscoveryInfo),
)
}
cdpRaw := packet.Layer(layers.LayerTypeCiscoDiscovery)
if cdpRaw != nil {
logger.Trace().Msgf("Found CDP Frame")
cdpInfo := packet.Layer(layers.LayerTypeCiscoDiscoveryInfo)
if cdpInfo == nil {
return fmt.Errorf("no CDP info layer")
}
return l.handlePacketCDP(
srcMac,
cdpRaw.(*layers.CiscoDiscovery),
cdpInfo.(*layers.CiscoDiscoveryInfo),
)
}
return nil
}
func (l *LLDP) handlePacketLLDP(mac string, raw *layers.LinkLayerDiscovery, info *layers.LinkLayerDiscoveryInfo) error {
n := &Neighbor{
Values: make(map[string]string),
Source: "lldp",
Mac: mac,
}
gotEnd := false
ttl := lldpDefaultTTL
for _, v := range raw.Values {
switch v.Type {
case layers.LLDPTLVEnd:
gotEnd = true
case layers.LLDPTLVChassisID:
n.ChassisID = string(raw.ChassisID.ID)
n.Values["chassis_id"] = n.ChassisID
case layers.LLDPTLVPortID:
n.PortID = string(raw.PortID.ID)
n.Values["port_id"] = n.PortID
case layers.LLDPTLVPortDescription:
n.PortDescription = info.PortDescription
n.Values["port_description"] = n.PortDescription
case layers.LLDPTLVSysName:
n.SystemName = info.SysName
n.Values["system_name"] = n.SystemName
case layers.LLDPTLVSysDescription:
n.SystemDescription = info.SysDescription
n.Values["system_description"] = n.SystemDescription
case layers.LLDPTLVMgmtAddress:
// n.ManagementAddress = info.MgmtAddress.Address
case layers.LLDPTLVTTL:
n.TTL = uint16(raw.TTL)
ttl = time.Duration(n.TTL) * time.Second
n.Values["ttl"] = fmt.Sprintf("%d", n.TTL)
case layers.LLDPTLVOrgSpecific:
for _, org := range info.OrgTLVs {
n.Values[fmt.Sprintf("org_specific_%d", org.OUI)] = string(org.Info)
}
}
}
if gotEnd || ttl < 1*time.Second {
l.deleteNeighbor(mac)
} else {
l.addNeighbor(mac, *n, ttl)
}
return nil
}
func (l *LLDP) handlePacketCDP(mac string, raw *layers.CiscoDiscovery, info *layers.CiscoDiscoveryInfo) error {
// TODO: implement full CDP parsing
n := &Neighbor{
Values: make(map[string]string),
Source: "cdp",
Mac: mac,
}
ttl := cdpDefaultTTL
n.ChassisID = info.DeviceID
n.PortID = info.PortID
n.SystemName = info.SysName
n.SystemDescription = info.Platform
n.TTL = uint16(raw.TTL)
if n.TTL > 1 {
ttl = time.Duration(n.TTL) * time.Second
}
if len(info.MgmtAddresses) > 0 {
n.ManagementAddress = string(info.MgmtAddresses[0])
}
l.addNeighbor(mac, *n, ttl)
return nil
}
func (l *LLDP) shutdownCapture() error {
if l.tPacket != nil {
l.l.Info().Msg("closing TPacket")
l.tPacket.Close()
l.tPacket = nil
}
if l.pktSource != nil {
l.l.Info().Msg("closing packet source")
l.pktSource = nil
}
return nil
}

View File

@ -48,7 +48,7 @@
{
"objID": "58af3ebb-96b3-494c-f4e3-9c23852e3e42",
"fileName": "actions.c",
"template": "#include \"actions.h\"\n#include \"screens.h\"\n\nint handle_gesture_screen_switch(lv_event_t *e, lv_dir_t direction, int screenId) {\n lv_event_code_t event_code = lv_event_get_code(e);\n if (event_code != LV_EVENT_GESTURE) {\n return 0;\n }\n\n if (lv_indev_get_gesture_dir(lv_indev_get_act()) != direction) {\n return 0;\n }\n lv_indev_wait_release(lv_indev_get_act());\n loadScreen(screenId);\n return 1;\n}\n\nvoid action_switch_to_menu(lv_event_t *e) {\n loadScreen(SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_switch_to_advanced_menu(lv_event_t *e) {\n loadScreen(SCREEN_ID_MENU_ADVANCED_SCREEN);\n}\n\nvoid action_switch_to_status(lv_event_t *e) {\n loadScreen(SCREEN_ID_STATUS_SCREEN);\n}\n\nvoid action_switch_to_about(lv_event_t *e) {\n loadScreen(SCREEN_ID_ABOUT_SCREEN);\n}\n\nvoid action_menu_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_HOME_SCREEN);\n}\n\nvoid action_menu_advanced_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_reset_config_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_ADVANCED_SCREEN);\n}\n\nvoid action_home_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_LEFT, SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_about_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);\n}"
"template": "#include \"actions.h\"\n#include \"screens.h\"\n\nint handle_gesture_screen_switch(lv_event_t *e, lv_dir_t direction, int screenId) {\n lv_event_code_t event_code = lv_event_get_code(e);\n if (event_code != LV_EVENT_GESTURE) {\n return 0;\n }\n\n if (lv_indev_get_gesture_dir(lv_indev_get_act()) != direction) {\n return 0;\n }\n lv_indev_wait_release(lv_indev_get_act());\n loadScreen(screenId);\n return 1;\n}\n\nvoid action_switch_to_menu(lv_event_t *e) {\n loadScreen(SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_switch_to_advanced_menu(lv_event_t *e) {\n loadScreen(SCREEN_ID_MENU_ADVANCED_SCREEN);\n}\n\nvoid action_switch_to_status(lv_event_t *e) {\n loadScreen(SCREEN_ID_STATUS_SCREEN);\n}\n\nvoid action_switch_to_about(lv_event_t *e) {\n loadScreen(SCREEN_ID_ABOUT_SCREEN);\n}\n\nvoid action_menu_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_HOME_SCREEN);\n}\n\nvoid action_menu_advanced_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_reset_config_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_home_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_LEFT, SCREEN_ID_MENU_SCREEN);\n}\n\nvoid action_about_screen_gesture(lv_event_t * e) {\n handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);\n}"
},
{
"objID": "1dbd1b7e-7270-47f0-ee02-e80bdae287cf",
@ -233,6 +233,14 @@
"localVariables": [],
"userProperties": [],
"name": "HandleCommonPressEvent"
},
{
"objID": "74dd35a7-73c0-4ab8-b02a-2c2b4ea411c8",
"components": [],
"connectionLines": [],
"localVariables": [],
"userProperties": [],
"name": "ResetConfig"
}
],
"userPages": [
@ -6370,6 +6378,641 @@
"isUsedAsUserWidget": false,
"createAtStart": true,
"deleteOnScreenUnload": false
},
{
"objID": "75ea84f5-a80e-419b-93b4-7153c186ade8",
"components": [
{
"objID": "80031032-9691-4aa9-c498-df60ab57c4b2",
"type": "LVGLScreenWidget",
"left": 0,
"top": 0,
"width": 300,
"height": 240,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "1619ccde-3843-4871-e9fa-8f0117af2488",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [
{
"objID": "28455dcc-0b2c-4a91-f778-fb0ea3610860",
"eventName": "GESTURE",
"handlerType": "action",
"action": "AboutScreenGesture",
"userData": 0
}
],
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "px",
"heightUnit": "px",
"children": [
{
"objID": "4fb18b2d-7616-4853-d070-6e195e06ece5",
"type": "LVGLContainerWidget",
"left": 0,
"top": 0,
"width": 100,
"height": 100,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "33aa8677-8ad3-4ab1-c6d3-994af54238b3",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [],
"identifier": "",
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "%",
"heightUnit": "%",
"children": [
{
"objID": "7db746f3-8899-43e3-c639-36be24c99641",
"type": "LVGLContainerWidget",
"left": 0,
"top": 0,
"width": 100,
"height": 32,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "1b33cd77-fd0c-4210-d97a-a1d1fa3d5b87",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [],
"identifier": "AboutHeaderContainer_1",
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "%",
"heightUnit": "content",
"children": [
{
"objID": "7b7ad394-ff9e-4a3b-bc57-835d9069a41a",
"type": "LVGLButtonWidget",
"left": 0,
"top": 0,
"width": 32,
"height": 32,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "ee403bac-e4be-4185-800e-c8ebfb43f0f8",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [
{
"objID": "5f651ba7-340c-4481-c2ed-c6952ef753d7",
"eventName": "CLICKED",
"handlerType": "action",
"action": "SwitchToMenu",
"userData": 0
}
],
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "px",
"heightUnit": "px",
"children": [
{
"objID": "5158d230-b879-40e9-fb63-8a67d47c7f5a",
"type": "LVGLImageWidget",
"left": -1,
"top": 2,
"width": 8,
"height": 12,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "c6220349-2a7b-43b6-eeb3-e83b4c9f9830",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [],
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "content",
"heightUnit": "content",
"children": [],
"widgetFlags": "ADV_HITTEST|CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE",
"hiddenFlagType": "literal",
"clickableFlagType": "literal",
"flagScrollbarMode": "",
"flagScrollDirection": "",
"scrollSnapX": "",
"scrollSnapY": "",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"localStyles": {
"objID": "2acf6cec-5cb1-48f5-fe9e-fb9f6b8a34dd"
},
"group": "",
"groupIndex": 0,
"image": "back-caret",
"setPivot": false,
"pivotX": 0,
"pivotY": 0,
"zoom": 256,
"angle": 0,
"innerAlign": "CENTER"
}
],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_ON_FOCUS|SCROLL_WITH_ARROW|SNAPPABLE",
"hiddenFlagType": "literal",
"clickableFlag": true,
"clickableFlagType": "literal",
"flagScrollbarMode": "",
"flagScrollDirection": "",
"scrollSnapX": "",
"scrollSnapY": "",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"useStyle": "BackButton",
"localStyles": {
"objID": "aa905e79-a9f2-41a9-dfa6-ba7c9a9d07b7"
},
"group": "",
"groupIndex": 0
},
{
"objID": "4bb0abba-9a53-40f1-9ba4-dc7ecae15005",
"type": "LVGLLabelWidget",
"left": 0,
"top": 0,
"width": 117,
"height": 20,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "883737b6-b175-4eb5-c072-95e67f7f140d",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [],
"identifier": "",
"leftUnit": "%",
"topUnit": "%",
"widthUnit": "content",
"heightUnit": "content",
"children": [],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE",
"hiddenFlagType": "literal",
"clickableFlagType": "literal",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"useStyle": "HeaderLink",
"localStyles": {
"objID": "a7abc8b4-5ce5-4506-8ecb-e4a3d059e35c"
},
"groupIndex": 0,
"text": "Reset Device",
"textType": "literal",
"longMode": "WRAP",
"recolor": false
}
],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE",
"hiddenFlagType": "literal",
"clickableFlag": true,
"clickableFlagType": "literal",
"flagScrollbarMode": "",
"flagScrollDirection": "",
"scrollSnapX": "",
"scrollSnapY": "",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"useStyle": "FlowRowSpaceBetween",
"localStyles": {
"objID": "71b261bf-896b-49ae-e6c8-5988ce9f2beb",
"definition": {
"MAIN": {
"DEFAULT": {
"pad_right": 4
}
}
}
},
"group": "",
"groupIndex": 0
},
{
"objID": "8730fe01-337a-4e8f-8767-1a4a9bd7ecf8",
"type": "LVGLContainerWidget",
"left": 0,
"top": 0,
"width": 100,
"height": 80,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "b5b7b2cf-88ec-40c5-a2d9-2de27b0be05f",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [],
"identifier": "AboutItemsContainer_1",
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "%",
"heightUnit": "%",
"children": [
{
"objID": "28edf722-8217-4ad1-834a-3df9a3c9beb6",
"type": "LVGLContainerWidget",
"left": 0,
"top": 0,
"width": 100,
"height": 118,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "bebac5ee-0e43-4f46-cb40-5250b4275680",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [],
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "%",
"heightUnit": "content",
"children": [
{
"objID": "d2955d4d-7acb-44d0-e221-9a458d569a3c",
"type": "LVGLContainerWidget",
"left": 0,
"top": 0,
"width": 100,
"height": 60,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "3745f1bf-b80b-4894-ef1d-3074a6b5f6f9",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [],
"identifier": "systemVersionContainer_1",
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "%",
"heightUnit": "content",
"children": [
{
"objID": "c18a5cbf-d0f7-45cd-d6f4-d26bb27b229a",
"type": "LVGLLabelWidget",
"left": 0,
"top": 0,
"width": 100,
"height": 40,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "06b4182d-0e0a-4b9b-d2fb-013a45b10d48",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [],
"identifier": "systemVersion_1",
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "%",
"heightUnit": "content",
"children": [],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE",
"hiddenFlagType": "literal",
"clickableFlagType": "literal",
"flagScrollbarMode": "",
"flagScrollDirection": "",
"scrollSnapX": "",
"scrollSnapY": "",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"useStyle": "InfoContentLabel",
"localStyles": {
"objID": "3adf240a-5ac9-4a43-e894-6204bded0ba8",
"definition": {
"MAIN": {
"DEFAULT": {
"text_font": "FontBook20"
}
}
}
},
"group": "",
"groupIndex": 0,
"text": "Press and hold for\n20 seconds",
"textType": "literal",
"longMode": "WRAP",
"recolor": false,
"previewValue": "0.0.1"
}
],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE",
"hiddenFlagType": "literal",
"clickableFlag": true,
"clickableFlagType": "literal",
"flagScrollbarMode": "",
"flagScrollDirection": "",
"scrollSnapX": "",
"scrollSnapY": "",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"useStyle": "FlexColumnStart",
"localStyles": {
"objID": "e3a2d4b4-9a5d-4789-cd9c-9b3145afe7c5",
"definition": {
"MAIN": {
"DEFAULT": {
"pad_right": 10,
"pad_left": 10,
"pad_top": 10,
"pad_bottom": 10
}
}
}
},
"group": "",
"groupIndex": 0
},
{
"objID": "e3c027f5-a51d-49ee-c7d6-74eca94fbf6a",
"type": "LVGLContainerWidget",
"left": 0,
"top": 0,
"width": 100,
"height": 50,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "c6616393-44b5-44c4-a7ba-2e7df5979370",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [],
"identifier": "appVersionContainer_1",
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "%",
"heightUnit": "content",
"children": [
{
"objID": "bf6a4dde-d627-4c38-9f0d-0d64b5740b1e",
"type": "LVGLButtonWidget",
"left": 0,
"top": 0,
"width": 100,
"height": 50,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "24a99368-5b88-43a0-fad7-586858d4ca9d",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [
{
"objID": "ecf97e0e-553c-4f12-d07d-75b8641d9374",
"eventName": "LONG_PRESSED",
"handlerType": "action",
"action": "ResetConfig",
"userData": 0
}
],
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "%",
"heightUnit": "px",
"children": [
{
"objID": "77fdf48f-8ae9-42e3-fff3-0b5b790e4779",
"type": "LVGLLabelWidget",
"left": 0,
"top": 0,
"width": 94,
"height": 16,
"customInputs": [],
"customOutputs": [],
"style": {
"objID": "2be8e2df-6e92-48c8-9a9b-79a3fad47cd4",
"useStyle": "default",
"conditionalStyles": [],
"childStyles": []
},
"timeline": [],
"eventHandlers": [],
"leftUnit": "px",
"topUnit": "px",
"widthUnit": "content",
"heightUnit": "content",
"children": [],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLLABLE|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE",
"hiddenFlagType": "literal",
"clickableFlagType": "literal",
"flagScrollbarMode": "",
"flagScrollDirection": "",
"scrollSnapX": "",
"scrollSnapY": "",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"localStyles": {
"objID": "e6b35e61-3c43-403d-f7bc-57f559f0b0c6",
"definition": {
"MAIN": {
"DEFAULT": {
"align": "CENTER",
"text_align": "LEFT"
}
}
}
},
"group": "",
"groupIndex": 0,
"text": "Hold to reset",
"textType": "literal",
"longMode": "WRAP",
"recolor": false
}
],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_ON_FOCUS|SCROLL_WITH_ARROW|SNAPPABLE",
"hiddenFlagType": "literal",
"clickableFlag": true,
"clickableFlagType": "literal",
"flagScrollbarMode": "",
"flagScrollDirection": "",
"scrollSnapX": "",
"scrollSnapY": "",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"useStyle": "",
"localStyles": {
"objID": "ae0e0a47-b565-4ed9-c58a-1d01bc4c6a64",
"definition": {
"MAIN": {
"DEFAULT": {
"bg_color": "DC2626",
"text_align": "LEFT",
"pad_right": 13
}
}
}
},
"group": "",
"groupIndex": 0
}
],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE",
"hiddenFlagType": "literal",
"clickableFlag": true,
"clickableFlagType": "literal",
"flagScrollbarMode": "",
"flagScrollDirection": "",
"scrollSnapX": "",
"scrollSnapY": "",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"useStyle": "FlexColumnStart",
"localStyles": {
"objID": "e3c2c8d3-f39f-4af9-c9b3-51281eaf3012"
},
"group": "",
"groupIndex": 0
}
],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE",
"hiddenFlagType": "literal",
"clickableFlag": true,
"clickableFlagType": "literal",
"flagScrollbarMode": "",
"flagScrollDirection": "",
"scrollSnapX": "",
"scrollSnapY": "",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"useStyle": "FlexColumnStart",
"localStyles": {
"objID": "ab7c25b4-573b-4158-d642-49507e72b05e",
"definition": {
"MAIN": {
"DEFAULT": {
"pad_right": 10
}
}
}
},
"group": "",
"groupIndex": 0
}
],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_VER|SNAPPABLE|SCROLL_ELASTIC|SCROLL_WITH_ARROW|SCROLL_MOMENTUM|SCROLL_CHAIN_HOR|SCROLLABLE",
"hiddenFlagType": "literal",
"clickableFlag": true,
"clickableFlagType": "literal",
"flagScrollbarMode": "auto",
"flagScrollDirection": "ver",
"scrollSnapX": "start",
"scrollSnapY": "",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"useStyle": "FlexColumnStart",
"localStyles": {
"objID": "ea6dd0a1-f5ea-49dc-c53a-e5e6ad5f7e38",
"definition": {
"MAIN": {
"DEFAULT": {
"pad_right": 4
}
}
}
},
"group": "",
"groupIndex": 0
}
],
"widgetFlags": "CLICK_FOCUSABLE|GESTURE_BUBBLE|PRESS_LOCK|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER|SCROLL_MOMENTUM|SCROLL_WITH_ARROW|SNAPPABLE|SCROLL_ELASTIC",
"hiddenFlagType": "literal",
"clickableFlag": true,
"clickableFlagType": "literal",
"flagScrollbarMode": "",
"flagScrollDirection": "",
"scrollSnapX": "",
"scrollSnapY": "",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"useStyle": "FlexStart",
"localStyles": {
"objID": "f8b4c1e4-75cd-41d0-d7ac-ae77f3bd041f"
},
"group": "",
"groupIndex": 0
}
],
"widgetFlags": "CLICKABLE|PRESS_LOCK|CLICK_FOCUSABLE|GESTURE_BUBBLE|SNAPPABLE|SCROLLABLE|SCROLL_ELASTIC|SCROLL_MOMENTUM|SCROLL_CHAIN_HOR|SCROLL_CHAIN_VER",
"hiddenFlagType": "literal",
"clickableFlag": true,
"clickableFlagType": "literal",
"checkedStateType": "literal",
"disabledStateType": "literal",
"states": "",
"useStyle": "FlexScreenMenu",
"localStyles": {
"objID": "d99a1659-8336-49a7-af47-8e80b522d52e"
},
"groupIndex": 0
}
],
"connectionLines": [],
"localVariables": [],
"userProperties": [],
"name": "ResetConfigScreen",
"left": 0,
"top": 0,
"width": 300,
"height": 240,
"isUsedAsUserWidget": false,
"createAtStart": true,
"deleteOnScreenUnload": false
}
],
"userWidgets": [],

View File

@ -1,12 +1,12 @@
{
"navigation": {
"selectedUserPageObject": "[jetkvm.eez-project]:/userPages/5",
"selectedActionObject": "[jetkvm.eez-project]:/actions/0",
"selectedUserPageObject": "[jetkvm.eez-project]:/userPages/8",
"selectedActionObject": "[jetkvm.eez-project]:/actions/5",
"selectedGlobalVariableObject": "[jetkvm.eez-project]:/variables/globalVariables/1",
"selectedStyleObject": "[jetkvm.eez-project]:/lvglStyles/styles/0",
"selectedStyleObject": "[jetkvm.eez-project]:/lvglStyles/styles/8",
"selectedThemeObject": "[jetkvm.eez-project]:/themes/0",
"selectedFontObject": "[jetkvm.eez-project]:/fonts/4",
"selectedBitmapObject": "[jetkvm.eez-project]:/bitmaps/11",
"selectedBitmapObject": "[jetkvm.eez-project]:/bitmaps/9",
"subnavigationSelectedItems": {
"variables-tab/sub-navigation/selected-item": "Global"
}
@ -30,7 +30,7 @@
{
"type": "border",
"selected": 2,
"size": 113.5,
"size": 296.5,
"location": "right",
"children": [
{
@ -77,7 +77,7 @@
},
{
"type": "border",
"selected": 1,
"selected": 0,
"location": "bottom",
"children": [
{
@ -130,6 +130,7 @@
"type": "tabset",
"id": "#2e3d9a08-c69c-42b5-b434-525109f2a5a7",
"weight": 1,
"selected": 1,
"enableClose": false,
"children": [
{
@ -188,19 +189,40 @@
"enableClose": false,
"icon": "svg:variable"
}
],
"active": true
]
}
]
},
{
"type": "tabset",
"id": "EDITORS",
"weight": 49.31058517127421,
"selected": 4,
"weight": 56.255429602160085,
"selected": 2,
"enableDeleteWhenEmpty": false,
"enableClose": false,
"children": [
{
"type": "tab",
"id": "#4610a27a-ce31-4747-b3c0-488eafeb606b",
"name": "StatusScreen",
"component": "editor",
"config": {
"objectPath": "[jetkvm.eez-project]:/userPages/7",
"permanent": false
},
"icon": "svg:page"
},
{
"type": "tab",
"id": "#ef9d764d-e942-47f4-beec-136cbd40ffd7",
"name": "ResetConfigScreen",
"component": "editor",
"config": {
"objectPath": "[jetkvm.eez-project]:/userPages/8",
"permanent": true
},
"icon": "svg:page"
},
{
"type": "tab",
"id": "#aec56ae8-5b75-4a2f-ad81-f0d7d683c77a",
@ -215,11 +237,11 @@
{
"type": "tab",
"id": "#c8dece00-e490-46b8-8a14-5dcfa8bbce36",
"name": "AboutScreen",
"name": "NoNetworkScreen",
"component": "editor",
"config": {
"objectPath": "[jetkvm.eez-project]:/userPages/5",
"permanent": false
"objectPath": "[jetkvm.eez-project]:/userPages/7",
"permanent": true
},
"icon": "svg:page"
},
@ -257,12 +279,13 @@
},
"icon": "material:settings"
}
]
],
"active": true
},
{
"type": "row",
"id": "#ee319cf9-6145-49e4-b40e-1d999be897c8",
"weight": 24.95234430353635,
"weight": 18.007499872650474,
"children": [
{
"type": "tabset",
@ -1065,8 +1088,7 @@
"0": {
"0": {
"0": {
"1": {},
"$selected": true
"1": {}
}
}
}
@ -1086,11 +1108,58 @@
}
},
"[jetkvm.eez-project]:/userPages/1[flow-state]": {
"selection": {
"0": {
"0": {
"0": {},
"1": {},
"$selected": true
}
}
},
"transform": {
"translate": {
"x": -180,
"y": -207
},
"scale": 1
},
"timeline": {
"isEditorActive": false,
"position": 0,
"secondToPx": 200,
"scrollLeft": 0
}
},
"[jetkvm.eez-project]:/lvglStyles/styles[tree-state]": {
"0": {},
"1": {},
"2": {},
"3": {},
"4": {
"$selected": true
},
"5": {
"$selected": true
},
"6": {
"$selected": true
},
"7": {
"$selected": true
},
"8": {
"$selected": true
}
},
"[jetkvm.eez-project]:/userPages/2[flow-state]": {
"selection": {
"0": {
"0": {
"0": {
"0": {},
"0": {
"$selected": true
},
"1": {
"0": {}
}
@ -1102,9 +1171,7 @@
"3": {
"0": {
"0": {},
"1": {
"$selected": true
}
"1": {}
},
"1": {
"0": {},
@ -1128,12 +1195,7 @@
"scrollLeft": 0
}
},
"[jetkvm.eez-project]:/lvglStyles/styles[tree-state]": {
"0": {
"$selected": true
}
},
"[jetkvm.eez-project]:/userPages/2[flow-state]": {
"[jetkvm.eez-project]:/userPages/3[flow-state]": {
"selection": {
"0": {
"0": {
@ -1142,13 +1204,14 @@
},
"1": {
"0": {
"0": {},
"0": {
"$selected": true
},
"1": {},
"2": {},
"3": {},
"4": {
"0": {},
"$selected": true
"0": {}
}
}
}
@ -1169,39 +1232,6 @@
"scrollLeft": 0
}
},
"[jetkvm.eez-project]:/userPages/3[flow-state]": {
"selection": {
"0": {
"0": {
"0": {
"0": {},
"$selected": true
},
"1": {
"0": {
"0": {},
"1": {},
"2": {},
"3": {}
}
}
}
}
},
"transform": {
"translate": {
"x": -150,
"y": -120
},
"scale": 1
},
"timeline": {
"isEditorActive": false,
"position": 0,
"secondToPx": 200,
"scrollLeft": 0
}
},
"[jetkvm.eez-project]:/userPages/4[flow-state]": {
"selection": {
"0": {
@ -1245,19 +1275,8 @@
"1": {
"0": {
"0": {},
"1": {
"1": {}
},
"2": {},
"3": {},
"4": {},
"5": {
"1": {
"$selected": true
}
},
"6": {},
"7": {}
"1": {},
"2": {}
}
}
}
@ -1300,10 +1319,68 @@
"0": {},
"1": {
"0": {
"0": {},
"0": {
"1": {}
},
"2": {
"1": {
"$selected": true
"1": {}
}
}
}
}
}
},
"transform": {
"translate": {
"x": -10.425644531250029,
"y": -122
},
"scale": 1
},
"timeline": {
"isEditorActive": false,
"position": 0,
"secondToPx": 200,
"scrollLeft": 0
}
},
"[jetkvm.eez-project]:/userPages/7[flow-state]": {
"selection": {
"0": {
"0": {
"0": {},
"1": {},
"$selected": true
}
}
},
"transform": {
"translate": {
"x": -180,
"y": -207
},
"scale": 1
},
"timeline": {
"isEditorActive": false,
"position": 0,
"secondToPx": 200,
"scrollLeft": 0
}
},
"[jetkvm.eez-project]:/userPages/8[flow-state]": {
"selection": {
"0": {
"0": {
"0": {},
"1": {
"0": {
"0": {},
"1": {
"0": {
"0": {
"$selected": true
}
}
}
}
@ -1313,8 +1390,8 @@
},
"transform": {
"translate": {
"x": -138,
"y": -122
"x": -194,
"y": -37
},
"scale": 1
},
@ -1339,10 +1416,12 @@
"logsPanelFilter": "all",
"selectedStylePropertyName": "",
"lvglPart": "MAIN",
"lvglState": "DISABLED",
"lvglState": "DEFAULT",
"lvglExpandedPropertiesGroup": [
"MARGIN",
"TEXT"
"TEXT",
"ARC",
"POSITION AND SIZE",
"PADDING"
],
"showInactiveFlowsInDebugger": true,
"globalFlowZoom": true,

View File

@ -40,7 +40,7 @@ void action_menu_advanced_screen_gesture(lv_event_t * e) {
}
void action_reset_config_screen_gesture(lv_event_t * e) {
handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_ADVANCED_SCREEN);
handle_gesture_screen_switch(e, LV_DIR_RIGHT, SCREEN_ID_MENU_SCREEN);
}
void action_home_screen_gesture(lv_event_t * e) {

View File

@ -20,6 +20,7 @@ extern void action_about_screen_gesture(lv_event_t * e);
extern void action_switch_to_status(lv_event_t * e);
extern void action_common_click_event(lv_event_t * e);
extern void action_handle_common_press_event(lv_event_t * e);
extern void action_reset_config(lv_event_t * e);
#ifdef __cplusplus

View File

@ -1719,6 +1719,188 @@ void create_screen_status_screen() {
void tick_screen_status_screen() {
}
void create_screen_reset_config_screen() {
lv_obj_t *obj = lv_obj_create(0);
objects.reset_config_screen = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, 300, 240);
lv_obj_add_event_cb(obj, action_about_screen_gesture, LV_EVENT_GESTURE, (void *)0);
add_style_flex_screen_menu(obj);
{
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_obj_create(parent_obj);
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_pad_left(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_top(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_right(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_bottom(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
add_style_flex_start(obj);
{
lv_obj_t *parent_obj = obj;
{
// AboutHeaderContainer_1
lv_obj_t *obj = lv_obj_create(parent_obj);
objects.about_header_container_1 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_pad_left(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_top(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_bottom(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
add_style_flow_row_space_between(obj);
lv_obj_set_style_pad_right(obj, 4, LV_PART_MAIN | LV_STATE_DEFAULT);
{
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_button_create(parent_obj);
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, 32, 32);
lv_obj_add_event_cb(obj, action_switch_to_menu, LV_EVENT_CLICKED, (void *)0);
add_style_back_button(obj);
{
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_image_create(parent_obj);
lv_obj_set_pos(obj, -1, 2);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_image_set_src(obj, &img_back_caret);
}
}
}
{
lv_obj_t *obj = lv_label_create(parent_obj);
lv_obj_set_pos(obj, LV_PCT(0), LV_PCT(0));
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
add_style_header_link(obj);
lv_label_set_text(obj, "Reset Device");
}
}
}
{
// AboutItemsContainer_1
lv_obj_t *obj = lv_obj_create(parent_obj);
objects.about_items_container_1 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_PCT(100), LV_PCT(80));
lv_obj_set_style_pad_left(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_top(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_bottom(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_AUTO);
lv_obj_set_scroll_dir(obj, LV_DIR_VER);
lv_obj_set_scroll_snap_x(obj, LV_SCROLL_SNAP_START);
add_style_flex_column_start(obj);
lv_obj_set_style_pad_right(obj, 4, LV_PART_MAIN | LV_STATE_DEFAULT);
{
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_obj_create(parent_obj);
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_pad_left(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_top(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_bottom(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
add_style_flex_column_start(obj);
lv_obj_set_style_pad_right(obj, 10, LV_PART_MAIN | LV_STATE_DEFAULT);
{
lv_obj_t *parent_obj = obj;
{
// systemVersionContainer_1
lv_obj_t *obj = lv_obj_create(parent_obj);
objects.system_version_container_1 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
add_style_flex_column_start(obj);
lv_obj_set_style_pad_right(obj, 10, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_left(obj, 10, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_top(obj, 10, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_bottom(obj, 10, LV_PART_MAIN | LV_STATE_DEFAULT);
{
lv_obj_t *parent_obj = obj;
{
// systemVersion_1
lv_obj_t *obj = lv_label_create(parent_obj);
objects.system_version_1 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT);
add_style_info_content_label(obj);
lv_obj_set_style_text_font(obj, &ui_font_font_book20, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_label_set_text(obj, "Press and hold for\n20 seconds");
}
}
}
{
// appVersionContainer_1
lv_obj_t *obj = lv_obj_create(parent_obj);
objects.app_version_container_1 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_pad_left(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_top(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_right(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_bottom(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_width(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_radius(obj, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
add_style_flex_column_start(obj);
{
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_button_create(parent_obj);
objects.obj0 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_PCT(100), 50);
lv_obj_add_event_cb(obj, action_reset_config, LV_EVENT_LONG_PRESSED, (void *)0);
lv_obj_set_style_bg_color(obj, lv_color_hex(0xffdc2626), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_right(obj, 13, LV_PART_MAIN | LV_STATE_DEFAULT);
{
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_label_create(parent_obj);
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_label_set_text(obj, "Hold to reset");
}
}
}
}
}
}
}
}
}
}
}
}
tick_screen_reset_config_screen();
}
void tick_screen_reset_config_screen() {
}
typedef void (*tick_screen_func_t)();
@ -1731,6 +1913,7 @@ tick_screen_func_t tick_screen_funcs[] = {
tick_screen_menu_network_screen,
tick_screen_about_screen,
tick_screen_status_screen,
tick_screen_reset_config_screen,
};
void tick_screen(int screen_index) {
tick_screen_funcs[screen_index]();
@ -1752,4 +1935,5 @@ void create_screens() {
create_screen_menu_network_screen();
create_screen_about_screen();
create_screen_status_screen();
create_screen_reset_config_screen();
}

View File

@ -16,6 +16,7 @@ typedef struct _objects_t {
lv_obj_t *menu_network_screen;
lv_obj_t *about_screen;
lv_obj_t *status_screen;
lv_obj_t *reset_config_screen;
lv_obj_t *boot_logo;
lv_obj_t *boot_screen_version;
lv_obj_t *no_network_header_container;
@ -83,6 +84,12 @@ typedef struct _objects_t {
lv_obj_t *app_version_1;
lv_obj_t *cloud_domain_container;
lv_obj_t *cloud_domain;
lv_obj_t *about_header_container_1;
lv_obj_t *about_items_container_1;
lv_obj_t *system_version_container_1;
lv_obj_t *system_version_1;
lv_obj_t *app_version_container_1;
lv_obj_t *obj0;
} objects_t;
extern objects_t objects;
@ -96,6 +103,7 @@ enum ScreensEnum {
SCREEN_ID_MENU_NETWORK_SCREEN = 6,
SCREEN_ID_ABOUT_SCREEN = 7,
SCREEN_ID_STATUS_SCREEN = 8,
SCREEN_ID_RESET_CONFIG_SCREEN = 9,
};
void create_screen_boot_screen();
@ -121,6 +129,9 @@ void tick_screen_about_screen();
void create_screen_status_screen();
void tick_screen_status_screen();
void create_screen_reset_config_screen();
void tick_screen_reset_config_screen();
void tick_screen_by_id(enum ScreensEnum screenId);
void tick_screen(int screen_index);

View File

@ -1,46 +0,0 @@
package network
import (
"errors"
"github.com/jetkvm/kvm/internal/lldp"
)
func (s *NetworkInterfaceState) shouldStartLLDP() bool {
if s.lldp == nil {
s.l.Trace().Msg("LLDP not initialized")
return false
}
s.l.Trace().Msgf("LLDP mode: %s", s.config.LLDPMode.String)
return s.config.LLDPMode.String != "disabled"
}
func (s *NetworkInterfaceState) startLLDP() {
if !s.shouldStartLLDP() || s.lldp == nil {
return
}
s.l.Trace().Msg("starting LLDP")
if err := s.lldp.Start(); err != nil {
s.l.Error().Err(err).Msg("unable to start LLDP")
}
}
func (s *NetworkInterfaceState) stopLLDP() {
if s.lldp == nil {
return
}
s.l.Trace().Msg("stopping LLDP")
if err := s.lldp.Stop(); err != nil {
s.l.Error().Err(err).Msg("unable to stop LLDP")
}
}
func (s *NetworkInterfaceState) GetLLDPNeighbors() ([]lldp.Neighbor, error) {
if s.lldp == nil {
return nil, errors.New("lldp not initialized")
}
return s.lldp.GetNeighbors(), nil
}

View File

@ -6,7 +6,6 @@ import (
"sync"
"github.com/jetkvm/kvm/internal/confparser"
"github.com/jetkvm/kvm/internal/lldp"
"github.com/jetkvm/kvm/internal/logging"
"github.com/jetkvm/kvm/internal/udhcpc"
"github.com/rs/zerolog"
@ -31,8 +30,6 @@ type NetworkInterfaceState struct {
config *NetworkConfig
dhcpClient *udhcpc.DHCPClient
lldp *lldp.LLDP
defaultHostname string
currentHostname string
currentFqdn string
@ -101,24 +98,7 @@ func NewNetworkInterfaceState(opts *NetworkInterfaceOptions) (*NetworkInterfaceS
},
})
// create the lldp service
lldpClient := lldp.NewLLDP(&lldp.LLDPOptions{
InterfaceName: opts.InterfaceName,
EnableRx: true,
EnableTx: true,
Logger: l,
})
// create the lldp service
lldpClient = lldp.NewLLDP(&lldp.LLDPOptions{
InterfaceName: opts.InterfaceName,
EnableRx: true,
EnableTx: true,
Logger: l,
})
s.dhcpClient = dhcpClient
s.lldp = lldpClient
return s, nil
}
@ -387,16 +367,13 @@ func (s *NetworkInterfaceState) updateNtpServersFromLease(lease *udhcpc.Lease) e
func (s *NetworkInterfaceState) handleInitialCheck() {
if s.IsUp() {
s.startLLDP()
}
s.onInitialCheck(s)
}
func (s *NetworkInterfaceState) handleStateChange() {
if s.IsUp() {
s.startLLDP()
} else {
s.stopLLDP()
}
s.onStateChange(s)
}

View File

@ -1259,5 +1259,4 @@ var rpcHandlers = map[string]RPCHandler{
"setKeyboardMacros": {Func: setKeyboardMacros, Params: []string{"params"}},
"getLocalLoopbackOnly": {Func: rpcGetLocalLoopbackOnly},
"setLocalLoopbackOnly": {Func: rpcSetLocalLoopbackOnly, Params: []string{"enabled"}},
"getLLDPNeighbors": {Func: rpcGetLLDPNeighbors},
}

View File

@ -3,7 +3,6 @@ package kvm
import (
"fmt"
"github.com/jetkvm/kvm/internal/lldp"
"github.com/jetkvm/kvm/internal/network"
"github.com/jetkvm/kvm/internal/udhcpc"
)
@ -124,7 +123,3 @@ func rpcSetNetworkSettings(settings network.RpcNetworkSettings) (*network.RpcNet
func rpcRenewDHCPLease() error {
return networkState.RpcRenewDHCPLease()
}
func rpcGetLLDPNeighbors() ([]lldp.Neighbor, error) {
return networkState.GetLLDPNeighbors()
}