11// === START_EXTENSION_CONFIG ===
22// {
3- // "name": "GVRET Manager ",
3+ // "name": "GVRET",
44// "id": "gvret-manager",
5- // "version": [1, 0 , 0],
5+ // "version": [1, 1 , 0],
66// "author": "JetPax",
7- // "description": "Manage GVRET Fastpath on ESP32 (CAN over TCP)",
7+ // "description": "Manage GVRET on MicroPython with mpDirect (CAN over TCP)",
88// "icon": "radio",
99// "menu": [
1010// { "id": "connection", "label": "Connection", "icon": "radio" },
11- // { "id": "filters", "label": "Filters", "icon": "filter" },
12- // { "id": "stats", "label": "Statistics", "icon": "activity" }
11+ // { "id": "filters", "label": "Filters", "icon": "filter" }
1312// ],
1413// "styles": ".gvret-container { padding: 20px; } .gvret-card { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 8px; padding: 20px; margin-bottom: 20px; } .gvret-card h3 { margin-top: 0; margin-bottom: 16px; border-bottom: 1px solid var(--border-color); padding-bottom: 8px; } .gvret-form-row { display: flex; gap: 16px; margin-bottom: 12px; align-items: center; } .gvret-form-row label { width: 100px; } .gvret-input { padding: 8px; border-radius: 4px; border: 1px solid var(--border-color); background: var(--bg-primary); color: var(--text-primary); } .gvret-btn { padding: 8px 16px; border-radius: 4px; border: none; cursor: pointer; font-weight: bold; } .gvret-btn-primary { background: var(--scheme-primary); color: white; } .gvret-btn-danger { background: #ef4444; color: white; } .gvret-filter-list { display: flex; flex-direction: column; gap: 8px; } .gvret-filter-item { display: flex; gap: 12px; padding: 8px; background: var(--bg-primary); border-radius: 4px; align-items: center; } .gvret-stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 16px; } .gvret-stat-card { background: var(--bg-primary); padding: 12px; border-radius: 4px; text-align: center; } .gvret-stat-value { font-size: 24px; font-weight: bold; color: var(--scheme-primary); } .gvret-stat-label { font-size: 12px; color: var(--text-secondary); }"
1514// }
@@ -26,16 +25,13 @@ class GVRETExtension {
2625 if ( ! this . state . gvret ) {
2726 this . state . gvret = {
2827 isRunning : false ,
29- txPin : 4 ,
30- rxPin : 5 ,
31- baudRate : 500000 ,
3228 filters : [ ] ,
3329 stats : { rx : 0 , tx : 0 , dropped : 0 }
3430 }
3531 }
3632 }
3733
38- // === Connection Panel ===
34+ // === Connection Panel (Combined with Statistics) ===
3935 renderConnection ( ) {
4036 const s = this . state . gvret
4137
@@ -44,32 +40,6 @@ class GVRETExtension {
4440 < div class ="gvret-card ">
4541 < h3 > GVRET Configuration</ h3 >
4642
47- < div class ="gvret-form-row ">
48- < label > TX Pin:</ label >
49- < input type ="number " class ="gvret-input " value ="${ s . txPin } "
50- onchange =${ ( e ) => { s . txPin = parseInt ( e . target . value ) ; this . emit ( 'render' ) ; } }
51- disabled =${ s . isRunning } />
52- </ div >
53-
54- < div class ="gvret-form-row ">
55- < label > RX Pin:</ label >
56- < input type ="number " class ="gvret-input " value ="${ s . rxPin } "
57- onchange =${ ( e ) => { s . rxPin = parseInt ( e . target . value ) ; this . emit ( 'render' ) ; } }
58- disabled =${ s . isRunning } />
59- </ div >
60-
61- < div class ="gvret-form-row ">
62- < label > Baud Rate:</ label >
63- < select class ="gvret-input " value ="${ s . baudRate } "
64- onchange =${ ( e ) => { s . baudRate = parseInt ( e . target . value ) ; this . emit ( 'render' ) ; } }
65- disabled =${ s . isRunning } >
66- < option value ="125000 "> 125 kbps</ option >
67- < option value ="250000 "> 250 kbps</ option >
68- < option value ="500000 "> 500 kbps</ option >
69- < option value ="1000000 "> 1 Mbps</ option >
70- </ select >
71- </ div >
72-
7343 < div class ="gvret-form-row " style ="margin-top: 20px; ">
7444 ${ ! s . isRunning ? this . html `
7545 < button class ="gvret-btn gvret-btn-primary " onclick =${ ( ) => this . startGVRET ( ) } >
@@ -85,6 +55,29 @@ class GVRETExtension {
8555 < div style ="margin-top: 16px; font-size: 14px; color: var(--text-secondary); ">
8656 < p > Status: < strong > ${ s . isRunning ? 'Running (Port 23)' : 'Stopped' } </ strong > </ p >
8757 ${ s . isRunning ? this . html `< p > Connect SavvyCAN to IP: < strong > ${ this . device . ip || 'Device IP' } </ strong > Port: < strong > 23</ strong > </ p > ` : '' }
58+ < p style ="margin-top: 8px; font-size: 12px; "> Using system CAN configuration (pins and bitrate configured in Networks → CAN)</ p >
59+ </ div >
60+ </ div >
61+
62+ < div class ="gvret-card ">
63+ < div style ="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; ">
64+ < h3 > Statistics</ h3 >
65+ < button class ="gvret-btn " onclick =${ ( ) => this . refreshStats ( ) } > Refresh</ button >
66+ </ div >
67+
68+ < div class ="gvret-stat-grid ">
69+ < div class ="gvret-stat-card ">
70+ < div class ="gvret-stat-value "> ${ s . stats . rx } </ div >
71+ < div class ="gvret-stat-label "> RX Frames</ div >
72+ </ div >
73+ < div class ="gvret-stat-card ">
74+ < div class ="gvret-stat-value "> ${ s . stats . tx } </ div >
75+ < div class ="gvret-stat-label "> TX Frames</ div >
76+ </ div >
77+ < div class ="gvret-stat-card ">
78+ < div class ="gvret-stat-value "> ${ s . stats . dropped } </ div >
79+ < div class ="gvret-stat-label "> Dropped</ div >
80+ </ div >
8881 </ div >
8982 </ div >
9083 </ div >
@@ -130,45 +123,66 @@ class GVRETExtension {
130123 `
131124 }
132125
133- // === Stats Panel ===
134- renderStats ( ) {
135- const s = this . state . gvret
136-
137- return this . html `
138- < div class ="gvret-container ">
139- < div class ="gvret-card ">
140- < div style ="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; ">
141- < h3 > Statistics</ h3 >
142- < button class ="gvret-btn " onclick =${ ( ) => this . refreshStats ( ) } > Refresh</ button >
143- </ div >
144-
145- < div class ="gvret-stat-grid ">
146- < div class ="gvret-stat-card ">
147- < div class ="gvret-stat-value "> ${ s . stats . rx } </ div >
148- < div class ="gvret-stat-label "> RX Frames</ div >
149- </ div >
150- < div class ="gvret-stat-card ">
151- < div class ="gvret-stat-value "> ${ s . stats . tx } </ div >
152- < div class ="gvret-stat-label "> TX Frames</ div >
153- </ div >
154- < div class ="gvret-stat-card ">
155- < div class ="gvret-stat-value "> ${ s . stats . dropped } </ div >
156- < div class ="gvret-stat-label "> Dropped</ div >
157- </ div >
158- </ div >
159- </ div >
160- </ div >
161- `
162- }
163126
164127 // === Actions ===
165128
166129 async startGVRET ( ) {
167130 const s = this . state . gvret
168131 try {
132+ // Read CAN configuration from /config/can.json
133+ const configResult = await this . device . execute ( `
134+ from lib.network_helpers import load_can_config
135+ import json
136+ import sys
137+
138+ # Load config and parse response
139+ try:
140+ load_can_config()
141+ # The response will be sent via webrepl.send(), so we need to capture it
142+ # For now, read directly from file
143+ import os
144+ config_dir = '/config'
145+ if not os.path.exists(config_dir):
146+ config_dir = '/store/config'
147+ config_file = config_dir + '/can.json'
148+
149+ try:
150+ with open(config_file, 'r') as f:
151+ config = json.load(f)
152+ print(f'CAN_TX_PIN={config.get("txPin", 5)}')
153+ print(f'CAN_RX_PIN={config.get("rxPin", 4)}')
154+ print(f'CAN_BITRATE={config.get("bitrate", 500000)}')
155+ except OSError:
156+ # Fallback to main.py if can.json doesn't exist
157+ sys.path.insert(0, '/device scripts')
158+ from main import CAN_TX_PIN, CAN_RX_PIN, CAN_BITRATE
159+ print(f'CAN_TX_PIN={CAN_TX_PIN}')
160+ print(f'CAN_RX_PIN={CAN_RX_PIN}')
161+ print(f'CAN_BITRATE={CAN_BITRATE}')
162+ except Exception as e:
163+ print(f'ERROR: {e}')
164+ # Fallback defaults
165+ print('CAN_TX_PIN=5')
166+ print('CAN_RX_PIN=4')
167+ print('CAN_BITRATE=500000')
168+ ` )
169+
170+ // Parse the output to get CAN pins and bitrate
171+ let txPin = 5 , rxPin = 4 , bitrate = 500000
172+ const lines = configResult . split ( '\n' )
173+ for ( const line of lines ) {
174+ if ( line . startsWith ( 'CAN_TX_PIN=' ) ) {
175+ txPin = parseInt ( line . split ( '=' ) [ 1 ] )
176+ } else if ( line . startsWith ( 'CAN_RX_PIN=' ) ) {
177+ rxPin = parseInt ( line . split ( '=' ) [ 1 ] )
178+ } else if ( line . startsWith ( 'CAN_BITRATE=' ) ) {
179+ bitrate = parseInt ( line . split ( '=' ) [ 1 ] )
180+ }
181+ }
182+
169183 await this . device . execute ( `
170184import gvret
171- gvret.start(${ s . txPin } , ${ s . rxPin } , ${ s . baudRate } )
185+ gvret.start(${ txPin } , ${ rxPin } , ${ bitrate } )
172186 ` )
173187 s . isRunning = true
174188 this . emit ( 'render' )
0 commit comments