paradigm shift

This commit is contained in:
ImBenji
2024-05-03 14:03:51 +01:00
parent 673891923d
commit 1f48f8f4b0
17 changed files with 2440 additions and 547 deletions

View File

@@ -37,8 +37,8 @@ android {
applicationId "com.imbenji.bus_infotainment"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
minSdkVersion 21
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled = true

View File

@@ -22,6 +22,8 @@
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
@@ -32,6 +34,9 @@
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="barcode_ui"/>
</application>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

View File

@@ -58,7 +58,7 @@ Route,Blind,51.4309209,-0.0936496
5,"Upton Park, Boleyn",51.5305005,0.0384915
5,"Plaistow, Balaam Street",51.5226426,0.0223686
5,"Canning Town, Barking Road",51.53044569999999,0.038323
5,Canning Town,51.5189494,0.0132
5,Canning Town,51.51395705923875, 0.00827546234713445
6,"Willesden, Bus Garage",51.5474482,-0.2394372
6,Kensal Rise,51.5345071,-0.2250186
6,Queen's Park,51.5345448,-0.2043853
@@ -216,8 +216,8 @@ Route,Blind,51.4309209,-0.0936496
20,Whipps Cross,51.581499,0.0001219
20,Woodford Green,51.6092549,0.0405521
20,Woodford Wells,51.6148287,0.0282889
20,Loughton,51.655942,0.068161
20,Debden,51.6042352,0.04159529999999999
20,Loughton,51.64195093723499, 0.05498357119784937
20,Debden,51.645776846753535, 0.08200009471482733
21,"Lewisham, Shopping Centre",51.46115090000001,-0.0073177
21,"Lewisham, Jerrard Street",51.4650045,-0.0164722
21,New Cross Gate,51.4749904,-0.0403466
@@ -719,7 +719,7 @@ Route,Blind,51.4309209,-0.0936496
69,Stratford,51.5426313,-0.0010369
69,Plaistow,51.5268317,0.0308143
69,"Canning Town, Hermit Road",51.5209368,0.0125057
69,Canning Town,51.5189494,0.0132
69,Canning Town,51.51395705923875, 0.00827546234713445
70,"Chiswick, Business Park",51.4930604,-0.2748696
70,"Acton, High Street",51.5068505,-0.2673267
70,East Acton Lane,51.5123715,-0.2543317
@@ -1066,7 +1066,7 @@ Route,Blind,51.4309209,-0.0936496
108,Stratford International Bus Station,51.5453665,-0.0099022
108,Bow Church,51.5287753,-0.0167013
108,"Poplar, All Saints",51.5105521,-0.0118612
108,Canning Town,51.5189494,0.0132
108,Canning Town,51.51395705923875, 0.00827546234713445
108,North Greenwich,51.4859576,0.007494900000000001
108,East Greenwich,51.4309209,-0.0936496
108,"Blackheath, Royal Standard",51.4779946,0.0202001
@@ -1128,7 +1128,7 @@ Route,Blind,51.4309209,-0.0936496
115,"Upton Park, Boleyn",51.5305005,0.0384915
115,"Plaistow, Balaam street",51.5260131,0.0238468
115,"Canning Town, Barking Road",51.5175196,0.0115068
115,Canning Town,51.5189494,0.0132
115,Canning Town,51.51395705923875, 0.00827546234713445
115,"Poplar, All Saints",51.5105521,-0.0118612
115,"Limehouse, Burdett Road",51.5209123,-0.0327503
115,"Stepney, Arbour Square",51.5140186,-0.0481747
@@ -1412,7 +1412,7 @@ Route,Blind,51.4309209,-0.0936496
147,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
147,"Upton Park, Boleyn",51.5305005,0.0384915
147,Prince Regent,51.5178274,0.0321034
147,Canning Town,51.5189494,0.0132
147,Canning Town,51.51395705923875, 0.00827546234713445
148,Camberwell Green,51.4756016,-0.0928896
148,Elephant & Castle,51.4938058,-0.0977932
148,Parliament Square,51.5010421,-0.1268514
@@ -1580,7 +1580,7 @@ Route,Blind,51.4309209,-0.0936496
167,"Barkingside, Fullwell Cross",51.59451199999999,0.08571999999999999
167,Gants Hill,51.5767812,0.0661732
167,Buckhurst Hill,51.627572,0.034513
167,Loughton,51.655942,0.068161
167,Loughton,51.64195093723499, 0.05498357119784937
168,Hampstead Heath,51.5608294,-0.1629416
168,Chalk Farm,51.5422732,-0.1466907
168,Camden Town,51.5390261,-0.1425516
@@ -1984,7 +1984,7 @@ Route,Blind,51.4309209,-0.0936496
212,Highams Park,51.6083754,0.0014712
212,"Walthamstow, Beacontree Avenue",51.595736,0.0045318
212,Walthamstow Central,51.5830128,-0.019886
212,St James Street,51.5064993,-0.1393328
212,St James Street,51.581118791593234, -0.0328839757764101
213,Kingston,51.4116616,-0.2080648
213,Kingston,51.4116616,-0.2080648
213,"New Malden, Coombe Road",51.4094312,-0.2586718
@@ -2202,7 +2202,7 @@ Route,Blind,51.4309209,-0.0936496
241,Plaistow,51.5268317,0.0308143
241,Plaistow Abbey Arms,51.5222296,0.0225853
241,Keir Hardie Estate,51.5678758,-0.0607466
241,Canning Town,51.5189494,0.0132
241,Canning Town,51.51395705923875, 0.00827546234713445
241,"Canning Town, Barking Road",51.5198077,0.0168462
242,Homerton Hospital,51.5478609,-0.0425903
242,"Clapton Park, Millfields",51.5575011,-0.0424329
@@ -2483,7 +2483,7 @@ Route,Blind,51.4309209,-0.0936496
274,Baker Street Station,51.5231548,-0.156863
274,Portman Square,51.5161534,-0.1560125
274,Marble Arch,51.5132225,-0.1588937
275,St James Street,51.5064993,-0.1393328
275,St James Street,51.581118791593234, -0.0328839757764101
275,Walthamstow Central,51.5830128,-0.019886
275,"Walthamstow, Beacontree Avenue",51.595736,0.0045318
275,Mill lane,51.5521985,-0.1932197
@@ -2685,7 +2685,7 @@ Route,Blind,51.4309209,-0.0936496
300,"Plaistow, Greengate Street",51.527444,0.027621
300,"Plaistow, Balaam Street",51.529212,0.0243676
300,"Canning Town, Barking Road",51.5208364,0.0191093
300,Canning Town,51.5189494,0.0132
300,Canning Town,51.51395705923875, 0.00827546234713445
302,Mill Hill Broadway,51.6129292,-0.2487871
302,Burnt Oak,51.602809,-0.266965
302,Burnt Oak,51.602809,-0.266965
@@ -2716,7 +2716,7 @@ Route,Blind,51.4309209,-0.0936496
308,Stratford City,51.5440354,-0.0053088
308,Homerton Hospital,51.5478609,-0.0425903
308,Clapton Pond,51.5561061,-0.05490830000000001
309,Canning Town,51.5189494,0.0132
309,Canning Town,51.51395705923875, 0.00827546234713445
309,Aberfeldy Estate,51.4309209,-0.0936496
309,"Poplar, All Saints",51.5105521,-0.0118612
309,"Poplar, Cordelia Street",51.5137347,-0.0174897
@@ -2805,7 +2805,7 @@ Route,Blind,51.4309209,-0.0936496
322,Brixton,51.4612794,-0.1156148
322,Clapham North,51.4658813,-0.1413263
322,Clapham Common,51.4589252,-0.1493071
323,Canning Town,51.5189494,0.0132
323,Canning Town,51.51395705923875, 0.00827546234713445
323,East London Mail Centre,51.55633,0.0655092
323,Mile End,51.52354529999999,-0.0330122
324,Stanmore Station,51.617676,-0.311451
@@ -2862,7 +2862,7 @@ Route,Blind,51.4309209,-0.0936496
330,"Upton Park, Boleyn",51.5305005,0.0384915
330,"Plaistow, Balaam Street",51.529212,0.0243676
330,"Canning Town, Barking Road",51.521274,0.0207211
330,Canning Town,51.5189494,0.0132
330,Canning Town,51.51395705923875, 0.00827546234713445
331,Ruislip,51.5758719,-0.421236
331,Ruislip Lido,51.59114049999999,-0.4304918
331,Northwood Station,51.6112297,-0.423889
@@ -3206,8 +3206,8 @@ Route,Blind,51.4309209,-0.0936496
397,"Crooked Billet, Sainsbury's",51.601088,-0.0159737
397,Chingford Mount,51.6185735,-0.0180318
397,Chingford Station,51.6331421,0.0098588
397,Loughton,51.655942,0.068161
397,Debden,51.5417031,0.2034589
397,Loughton,51.64195093723499, 0.05498357119784937
397,Debden,51.645776846753535, 0.08200009471482733
398,Ruislip,51.5758719,-0.421236
398,Rayners Lane Station,51.5751034,-0.3708618
398,South Harrow,51.5683717,-0.3553483
@@ -3521,7 +3521,7 @@ Route,Blind,51.4309209,-0.0936496
473,Plaistow,51.5268317,0.0308143
473,Stratford,51.5426313,-0.0010369
474,"Canning Town, Barking Road",51.52364720000001,0.0258453
474,Canning Town,51.5189494,0.0132
474,Canning Town,51.51395705923875, 0.00827546234713445
474,London City Airport,51.5048437,0.049518
474,North Woolwich,51.5008658,0.0626916
474,Cyprus,51.5091192,0.0633823
@@ -3658,7 +3658,7 @@ Route,Blind,51.4309209,-0.0936496
541,Prince Regent,51.4309209,-0.0936496
549,South Woodford,51.5912671,0.0264721
549,Buckhurst Hill,51.627572,0.034513
549,Loughton,51.655942,0.068161
549,Loughton,51.64195093723499, 0.05498357119784937
601,Thamesmead,51.50575809999999,0.1100586
601,Bexley,51.439933,0.154327
601,Wilmington Schools,51.4309209,-0.0936496
@@ -3803,7 +3803,7 @@ Route,Blind,51.4309209,-0.0936496
673,Beckton Station,51.5144016,0.06153319999999999
674,"Harold Hill, Dagnam Park Square",51.6049149,0.2445527
674,Romford Station,51.57472449999999,0.1826519
675,St James Street,51.5064993,-0.1393328
675,St James Street,51.581118791593234, -0.0328839757764101
675,Woodbridge School,51.4309209,-0.0936496
678,Stratford,51.5426313,-0.0010369
678,NO BLIND DESCRIPTION (Departs only),51.4309209,-0.0936496
@@ -4016,7 +4016,7 @@ EL1,Barking,51.536563,0.075766
EL1,Barking,51.536563,0.075766
EL1,"River Road, Waverley Gardens",51.5343317,-0.2891878
EL1,"River Road, Waverley Gardens",51.5343317,-0.2891878
EL1,Barking Riverside,51.536563,0.075766
EL1,Barking Riverside,51.519303731473705, 0.11590257503355633
EL2,Becontree Heath,51.5609465,0.1488995
EL2,Five Elms,51.3697855,0.0259964
EL2,Bennett's Castle Lane,51.5562949,0.1276031
@@ -4031,7 +4031,7 @@ EL3,"Goodmayes, Goodmayes Lane",51.5620979,0.1095257
EL3,Barking,51.536563,0.075766
EL3,Creekmouth,51.517381,0.102234
EL3,Barking,51.536563,0.075766
EL3,Barking Riverside,51.536563,0.075766
EL3,Barking Riverside,51.519303731473705, 0.11590257503355633
G1,"Streatham, Green Lane",51.4147104,-0.1158693
G1,"Streatham, St Leonard's Church",51.4307467,-0.1294977
G1,Tooting Broadway,51.427867,-0.1678142
@@ -4411,7 +4411,7 @@ UL10,Hackney Downs,51.5553095,-0.06908249999999999
UL10,Liverpool Street,51.5175001,-0.0826966
UL11,Canary Wharf,51.5054306,-0.0235333
UL11,Stratford,51.5426313,-0.0010369
UL12,Loughton,51.655942,0.068161
UL12,Loughton,51.64195093723499, 0.05498357119784937
UL12,Snaresbrook,51.58567859999999,0.0084531
UL12,Leyton,51.5702225,-0.0146938
UL12,Stratford,51.5426313,-0.0010369
@@ -4438,7 +4438,7 @@ UL19,Wembley Central,51.550501,-0.3048409
UL19,Stonebridge Park,51.5445824,-0.2608244
UL19,Queen's Park,51.5345448,-0.2043853
UL20,Tower Hill,51.5095757,-0.0760083
UL20,Canning Town,51.5189494,0.0132
UL20,Canning Town,51.51395705923875, 0.00827546234713445
UL20,Stratford,51.5426313,-0.0010369
UL20,Stratford,51.5426313,-0.0010369
UL20,East Ham,51.5333972,0.04991139999999999
@@ -4540,7 +4540,7 @@ W11,"Walthamstow, Crooked Billet",51.601088,-0.0159737
W11,Walthamstow Central,51.5830128,-0.019886
W12,"Walthamstow, Coppermill Lane",51.5803038,-0.0403725
W12,Walthamstow Central,51.5830128,-0.019886
W12,St James Street,51.5064993,-0.1393328
W12,St James Street,51.581118791593234, -0.0328839757764101
W12,Whipps Cross,51.5095281,-0.229236
W12,South Woodford,51.5095281,-0.229236
W12,Wanstead,51.5767971,0.0249881
@@ -4559,7 +4559,7 @@ W14,"Leytonstone, Harrow Green",51.5582955,0.007356
W14,Leyton,51.4964278,-0.2085211
W14,"Leyton, Superstores",51.5558965,-0.0093311
W15,"Higham Hill, Cogan Avenue",51.6012336,-0.0363719
W15,"Forest Road, Palmerston Road",51.5858953,-0.0292291
W15,"Forest Road, Palmerston Road",51.588898351903815, -0.030623848707334166
W15,Walthamstow Central,51.5830128,-0.019886
W15,"Leyton, Bakers Arms",51.5749185,-0.013549
W15,Whipps Cross,51.581499,0.0001219
@@ -4576,7 +4576,7 @@ W16,"Walthamstow, Wood Street",51.5864747,-0.0026968
W16,"Leyton, Bakers Arms",51.5749185,-0.013549
W16,Leytonstone,51.5649624,0.0088141
W19,"Walthamstow, Argall Avenue",51.5701165,-0.0387872
W19,St James Street,51.5064993,-0.1393328
W19,St James Street,51.581118791593234, -0.0328839757764101
W19,Walthamstow Central,51.5830128,-0.019886
W19,Whipps Cross,51.4255297,-0.2050566
W19,Leytonstone,51.5649624,0.0088141
@@ -4704,7 +4704,7 @@ N15,Barking,51.5833519,-0.07649299999999999
N15,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
N15,Upton Park,51.53471750000001,0.0337596
N15,"Canning Town, Barking Road",51.5180017,0.0130984
N15,Canning Town,51.5189494,0.0132
N15,Canning Town,51.51395705923875, 0.00827546234713445
N15,"Poplar, All Saints",51.5105521,-0.0118612
N15,"Limehouse, Burdett Road",51.5150014,-0.0285662
N15,Aldgate,51.5134365,-0.0772463
@@ -5151,13 +5151,13 @@ N550,Aldgate,51.5134365,-0.0772463
N550,Cannon Street,51.5119949,-0.091962
N550,"Limehouse, Burdett Road",51.5150014,-0.0285662
N550,"Poplar, All Saints",51.5105521,-0.0118612
N550,Canning Town,51.5189494,0.0132
N550,Canning Town,51.51395705923875, 0.00827546234713445
N551,Trafalgar Square,51.508039,-0.128069
N551,Aldwych,51.5132441,-0.1172819
N551,Aldgate,51.5134365,-0.0772463
N551,Limehouse,51.5110598,-0.0366652
N551,"Poplar, All Saints",51.5105521,-0.0118612
N551,Canning Town,51.5189494,0.0132
N551,Canning Town,51.51395705923875, 0.00827546234713445
N551,Keir Hardie Estate,51.5678758,-0.0607466
N551,Prince Regent,51.4309209,-0.0936496
N551,Beckton Station,51.5144016,0.06153319999999999
1 Route Blind 51.4309209 -0.0936496
58 5 Upton Park, Boleyn 51.5305005 0.0384915
59 5 Plaistow, Balaam Street 51.5226426 0.0223686
60 5 Canning Town, Barking Road 51.53044569999999 0.038323
61 5 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
62 6 Willesden, Bus Garage 51.5474482 -0.2394372
63 6 Kensal Rise 51.5345071 -0.2250186
64 6 Queen's Park 51.5345448 -0.2043853
216 20 Whipps Cross 51.581499 0.0001219
217 20 Woodford Green 51.6092549 0.0405521
218 20 Woodford Wells 51.6148287 0.0282889
219 20 Loughton 51.655942 51.64195093723499 0.068161 0.05498357119784937
220 20 Debden 51.6042352 51.645776846753535 0.04159529999999999 0.08200009471482733
221 21 Lewisham, Shopping Centre 51.46115090000001 -0.0073177
222 21 Lewisham, Jerrard Street 51.4650045 -0.0164722
223 21 New Cross Gate 51.4749904 -0.0403466
719 69 Stratford 51.5426313 -0.0010369
720 69 Plaistow 51.5268317 0.0308143
721 69 Canning Town, Hermit Road 51.5209368 0.0125057
722 69 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
723 70 Chiswick, Business Park 51.4930604 -0.2748696
724 70 Acton, High Street 51.5068505 -0.2673267
725 70 East Acton Lane 51.5123715 -0.2543317
1066 108 Stratford International Bus Station 51.5453665 -0.0099022
1067 108 Bow Church 51.5287753 -0.0167013
1068 108 Poplar, All Saints 51.5105521 -0.0118612
1069 108 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
1070 108 North Greenwich 51.4859576 0.007494900000000001
1071 108 East Greenwich 51.4309209 -0.0936496
1072 108 Blackheath, Royal Standard 51.4779946 0.0202001
1128 115 Upton Park, Boleyn 51.5305005 0.0384915
1129 115 Plaistow, Balaam street 51.5260131 0.0238468
1130 115 Canning Town, Barking Road 51.5175196 0.0115068
1131 115 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
1132 115 Poplar, All Saints 51.5105521 -0.0118612
1133 115 Limehouse, Burdett Road 51.5209123 -0.0327503
1134 115 Stepney, Arbour Square 51.5140186 -0.0481747
1412 147 East Ham, Newham Town Hall 51.53280239999999 0.0551608
1413 147 Upton Park, Boleyn 51.5305005 0.0384915
1414 147 Prince Regent 51.5178274 0.0321034
1415 147 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
1416 148 Camberwell Green 51.4756016 -0.0928896
1417 148 Elephant & Castle 51.4938058 -0.0977932
1418 148 Parliament Square 51.5010421 -0.1268514
1580 167 Barkingside, Fullwell Cross 51.59451199999999 0.08571999999999999
1581 167 Gants Hill 51.5767812 0.0661732
1582 167 Buckhurst Hill 51.627572 0.034513
1583 167 Loughton 51.655942 51.64195093723499 0.068161 0.05498357119784937
1584 168 Hampstead Heath 51.5608294 -0.1629416
1585 168 Chalk Farm 51.5422732 -0.1466907
1586 168 Camden Town 51.5390261 -0.1425516
1984 212 Highams Park 51.6083754 0.0014712
1985 212 Walthamstow, Beacontree Avenue 51.595736 0.0045318
1986 212 Walthamstow Central 51.5830128 -0.019886
1987 212 St James Street 51.5064993 51.581118791593234 -0.1393328 -0.0328839757764101
1988 213 Kingston 51.4116616 -0.2080648
1989 213 Kingston 51.4116616 -0.2080648
1990 213 New Malden, Coombe Road 51.4094312 -0.2586718
2202 241 Plaistow 51.5268317 0.0308143
2203 241 Plaistow Abbey Arms 51.5222296 0.0225853
2204 241 Keir Hardie Estate 51.5678758 -0.0607466
2205 241 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
2206 241 Canning Town, Barking Road 51.5198077 0.0168462
2207 242 Homerton Hospital 51.5478609 -0.0425903
2208 242 Clapton Park, Millfields 51.5575011 -0.0424329
2483 274 Baker Street Station 51.5231548 -0.156863
2484 274 Portman Square 51.5161534 -0.1560125
2485 274 Marble Arch 51.5132225 -0.1588937
2486 275 St James Street 51.5064993 51.581118791593234 -0.1393328 -0.0328839757764101
2487 275 Walthamstow Central 51.5830128 -0.019886
2488 275 Walthamstow, Beacontree Avenue 51.595736 0.0045318
2489 275 Mill lane 51.5521985 -0.1932197
2685 300 Plaistow, Greengate Street 51.527444 0.027621
2686 300 Plaistow, Balaam Street 51.529212 0.0243676
2687 300 Canning Town, Barking Road 51.5208364 0.0191093
2688 300 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
2689 302 Mill Hill Broadway 51.6129292 -0.2487871
2690 302 Burnt Oak 51.602809 -0.266965
2691 302 Burnt Oak 51.602809 -0.266965
2716 308 Stratford City 51.5440354 -0.0053088
2717 308 Homerton Hospital 51.5478609 -0.0425903
2718 308 Clapton Pond 51.5561061 -0.05490830000000001
2719 309 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
2720 309 Aberfeldy Estate 51.4309209 -0.0936496
2721 309 Poplar, All Saints 51.5105521 -0.0118612
2722 309 Poplar, Cordelia Street 51.5137347 -0.0174897
2805 322 Brixton 51.4612794 -0.1156148
2806 322 Clapham North 51.4658813 -0.1413263
2807 322 Clapham Common 51.4589252 -0.1493071
2808 323 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
2809 323 East London Mail Centre 51.55633 0.0655092
2810 323 Mile End 51.52354529999999 -0.0330122
2811 324 Stanmore Station 51.617676 -0.311451
2862 330 Upton Park, Boleyn 51.5305005 0.0384915
2863 330 Plaistow, Balaam Street 51.529212 0.0243676
2864 330 Canning Town, Barking Road 51.521274 0.0207211
2865 330 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
2866 331 Ruislip 51.5758719 -0.421236
2867 331 Ruislip Lido 51.59114049999999 -0.4304918
2868 331 Northwood Station 51.6112297 -0.423889
3206 397 Crooked Billet, Sainsbury's 51.601088 -0.0159737
3207 397 Chingford Mount 51.6185735 -0.0180318
3208 397 Chingford Station 51.6331421 0.0098588
3209 397 Loughton 51.655942 51.64195093723499 0.068161 0.05498357119784937
3210 397 Debden 51.5417031 51.645776846753535 0.2034589 0.08200009471482733
3211 398 Ruislip 51.5758719 -0.421236
3212 398 Rayners Lane Station 51.5751034 -0.3708618
3213 398 South Harrow 51.5683717 -0.3553483
3521 473 Plaistow 51.5268317 0.0308143
3522 473 Stratford 51.5426313 -0.0010369
3523 474 Canning Town, Barking Road 51.52364720000001 0.0258453
3524 474 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
3525 474 London City Airport 51.5048437 0.049518
3526 474 North Woolwich 51.5008658 0.0626916
3527 474 Cyprus 51.5091192 0.0633823
3658 541 Prince Regent 51.4309209 -0.0936496
3659 549 South Woodford 51.5912671 0.0264721
3660 549 Buckhurst Hill 51.627572 0.034513
3661 549 Loughton 51.655942 51.64195093723499 0.068161 0.05498357119784937
3662 601 Thamesmead 51.50575809999999 0.1100586
3663 601 Bexley 51.439933 0.154327
3664 601 Wilmington Schools 51.4309209 -0.0936496
3803 673 Beckton Station 51.5144016 0.06153319999999999
3804 674 Harold Hill, Dagnam Park Square 51.6049149 0.2445527
3805 674 Romford Station 51.57472449999999 0.1826519
3806 675 St James Street 51.5064993 51.581118791593234 -0.1393328 -0.0328839757764101
3807 675 Woodbridge School 51.4309209 -0.0936496
3808 678 Stratford 51.5426313 -0.0010369
3809 678 NO BLIND DESCRIPTION (Departs only) 51.4309209 -0.0936496
4016 EL1 Barking 51.536563 0.075766
4017 EL1 River Road, Waverley Gardens 51.5343317 -0.2891878
4018 EL1 River Road, Waverley Gardens 51.5343317 -0.2891878
4019 EL1 Barking Riverside 51.536563 51.519303731473705 0.075766 0.11590257503355633
4020 EL2 Becontree Heath 51.5609465 0.1488995
4021 EL2 Five Elms 51.3697855 0.0259964
4022 EL2 Bennett's Castle Lane 51.5562949 0.1276031
4031 EL3 Barking 51.536563 0.075766
4032 EL3 Creekmouth 51.517381 0.102234
4033 EL3 Barking 51.536563 0.075766
4034 EL3 Barking Riverside 51.536563 51.519303731473705 0.075766 0.11590257503355633
4035 G1 Streatham, Green Lane 51.4147104 -0.1158693
4036 G1 Streatham, St Leonard's Church 51.4307467 -0.1294977
4037 G1 Tooting Broadway 51.427867 -0.1678142
4411 UL10 Liverpool Street 51.5175001 -0.0826966
4412 UL11 Canary Wharf 51.5054306 -0.0235333
4413 UL11 Stratford 51.5426313 -0.0010369
4414 UL12 Loughton 51.655942 51.64195093723499 0.068161 0.05498357119784937
4415 UL12 Snaresbrook 51.58567859999999 0.0084531
4416 UL12 Leyton 51.5702225 -0.0146938
4417 UL12 Stratford 51.5426313 -0.0010369
4438 UL19 Stonebridge Park 51.5445824 -0.2608244
4439 UL19 Queen's Park 51.5345448 -0.2043853
4440 UL20 Tower Hill 51.5095757 -0.0760083
4441 UL20 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
4442 UL20 Stratford 51.5426313 -0.0010369
4443 UL20 Stratford 51.5426313 -0.0010369
4444 UL20 East Ham 51.5333972 0.04991139999999999
4540 W11 Walthamstow Central 51.5830128 -0.019886
4541 W12 Walthamstow, Coppermill Lane 51.5803038 -0.0403725
4542 W12 Walthamstow Central 51.5830128 -0.019886
4543 W12 St James Street 51.5064993 51.581118791593234 -0.1393328 -0.0328839757764101
4544 W12 Whipps Cross 51.5095281 -0.229236
4545 W12 South Woodford 51.5095281 -0.229236
4546 W12 Wanstead 51.5767971 0.0249881
4559 W14 Leyton 51.4964278 -0.2085211
4560 W14 Leyton, Superstores 51.5558965 -0.0093311
4561 W15 Higham Hill, Cogan Avenue 51.6012336 -0.0363719
4562 W15 Forest Road, Palmerston Road 51.5858953 51.588898351903815 -0.0292291 -0.030623848707334166
4563 W15 Walthamstow Central 51.5830128 -0.019886
4564 W15 Leyton, Bakers Arms 51.5749185 -0.013549
4565 W15 Whipps Cross 51.581499 0.0001219
4576 W16 Leyton, Bakers Arms 51.5749185 -0.013549
4577 W16 Leytonstone 51.5649624 0.0088141
4578 W19 Walthamstow, Argall Avenue 51.5701165 -0.0387872
4579 W19 St James Street 51.5064993 51.581118791593234 -0.1393328 -0.0328839757764101
4580 W19 Walthamstow Central 51.5830128 -0.019886
4581 W19 Whipps Cross 51.4255297 -0.2050566
4582 W19 Leytonstone 51.5649624 0.0088141
4704 N15 East Ham, Newham Town Hall 51.53280239999999 0.0551608
4705 N15 Upton Park 51.53471750000001 0.0337596
4706 N15 Canning Town, Barking Road 51.5180017 0.0130984
4707 N15 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
4708 N15 Poplar, All Saints 51.5105521 -0.0118612
4709 N15 Limehouse, Burdett Road 51.5150014 -0.0285662
4710 N15 Aldgate 51.5134365 -0.0772463
5151 N550 Cannon Street 51.5119949 -0.091962
5152 N550 Limehouse, Burdett Road 51.5150014 -0.0285662
5153 N550 Poplar, All Saints 51.5105521 -0.0118612
5154 N550 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
5155 N551 Trafalgar Square 51.508039 -0.128069
5156 N551 Aldwych 51.5132441 -0.1172819
5157 N551 Aldgate 51.5134365 -0.0772463
5158 N551 Limehouse 51.5110598 -0.0366652
5159 N551 Poplar, All Saints 51.5105521 -0.0118612
5160 N551 Canning Town 51.5189494 51.51395705923875 0.0132 0.00827546234713445
5161 N551 Keir Hardie Estate 51.5678758 -0.0607466
5162 N551 Prince Regent 51.4309209 -0.0936496
5163 N551 Beckton Station 51.5144016 0.06153319999999999

View File

@@ -1,8 +1,8 @@
class ApiConstants {
static const String APPWRITE_ENDPOINT = "https://cloud.imbenji.net/v1";
static const String APPWRITE_PROJECT_ID = "65de530c1c0a7ffc0c3f";
static const String APPWRITE_ENDPOINT = "https://cloud.appwrite.io/v1";
static const String APPWRITE_PROJECT_ID = "6633d0e00023502890ed";
static const String INFO_Q_DATABASE_ID = "65de5cab16717444527b";
static const String MANUAL_Q_COLLECTION_ID = "65de9f2f925562a2eda8";

View File

@@ -21,6 +21,7 @@ class AuthAPI extends ChangeNotifier {
late final appwrite.Account account;
late models.User _currentUser;
late models.Session _currentSession;
AuthStatus _status = AuthStatus.UNINITIALIZED;
@@ -32,11 +33,16 @@ class AuthAPI extends ChangeNotifier {
AuthStatus get status => _status;
String? get username => _currentUser.name;
String? get email => _currentUser.email;
String? get userID => _currentUser.$id;
String? get userID {
try {
return _currentUser.$id;
} catch (e) {
return _currentSession.$id;
}
}
AuthAPI() {
AuthAPI({bool autoLoad = true}) {
init();
loadUser();
}
init() {
@@ -45,6 +51,29 @@ class AuthAPI extends ChangeNotifier {
.setProject(ApiConstants.APPWRITE_PROJECT_ID)
.setSelfSigned();
account = appwrite.Account(client);
try {
account.get().then((value) {
_currentUser = value;
_status = AuthStatus.AUTHENTICATED;
print("Auto loaded user: ${_currentUser.name}");
print("Auth status: $_status");
});
} catch (e) {
}
}
loadAnonymousUser() async {
try {
final user = await account.createAnonymousSession();
_currentSession = user;
_status = AuthStatus.AUTHENTICATED;
} catch (e) {
_status = AuthStatus.UNAUTHENTICATED;
} finally {
notifyListeners();
}
}
loadUser() async {

View File

@@ -16,6 +16,7 @@ import 'package:bus_infotainment/backend/modules/tube_info.dart';
import 'package:bus_infotainment/tfl_datasets.dart';
import 'package:bus_infotainment/utils/audio%20wrapper.dart';
import 'package:bus_infotainment/utils/delegates.dart';
import 'package:bus_infotainment/workaround/keepalive_realtime.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
@@ -62,12 +63,6 @@ class LiveInformation {
print("Loading tube stations from assets");
tubeStations = TubeStations.fromJson(json.decode(await rootBundle.loadString("assets/datasets/tube_stations.json")));
print("Loaded tube stations from assets");
String sessionID = "test";
commandModule = CommandModule(sessionID);
}
// Initialise modules
@@ -77,6 +72,9 @@ class LiveInformation {
initTrackerModule();
print("Initialised LiveInformation");
if (!auth.isAuthenticated()) {
auth.loadAnonymousUser();
}
}
Future<void> initTrackerModule() async {
@@ -86,10 +84,18 @@ class LiveInformation {
}
// Auth
AuthAPI auth = AuthAPI();
AuthAPI auth = AuthAPI(
autoLoad: false,
);
String? roomCode;
String? roomDocumentID;
bool isHost = false;
appwrite.RealtimeSubscription? _subscription;
RealtimeKeepAliveConnection? _keepAliveConnection; // This is a workaround for a bug in the appwrite SDK
// Modules
late CommandModule commandModule;
// late CommandModule commandModule; This needs to be deprecated
late BusSequences busSequences;
late AnnouncementModule announcementModule;
late SyncedTimeModule syncedTimeModule;
@@ -100,7 +106,7 @@ class LiveInformation {
BusRouteVariant? _currentRouteVariant;
// Events
EventDelegate<BusRouteVariant> routeVariantDelegate = EventDelegate();
EventDelegate<BusRouteVariant?> routeVariantDelegate = EventDelegate();
// Internal methods
@@ -108,7 +114,54 @@ class LiveInformation {
Future<void> setRouteVariant_Internal(BusRouteVariant routeVariant) async {
Future<void> setRouteVariant(BusRouteVariant? routeVariant) async {
if (routeVariant == null) {
_currentRouteVariant = null;
await announcementModule.queueAnnounceByAudioName(
displayText: "*** NO MESSAGE ***",
);
routeVariantDelegate.trigger(null);
return;
}
if (roomCode != null) {
try {
final client = auth.client;
final databases = appwrite.Databases(client);
final response = await databases.listDocuments(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
queries: [
appwrite.Query.search("SessionID", roomCode!)
]
);
final document = response.documents.first;
// Check if the route is not the same
if (document.data["CurrentRoute"] != routeVariant.busRoute.routeNumber || document.data["CurrentRouteVariant"] != routeVariant.busRoute.routeVariants.values.toList().indexOf(routeVariant)) {
final updatedDocument = await databases.updateDocument(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
documentId: document.$id,
data: {
"CurrentRoute": routeVariant.busRoute.routeNumber,
"CurrentRouteVariant": routeVariant.busRoute.routeVariants.values.toList().indexOf(routeVariant),
"LastUpdater": auth.userID,
}
);
print("Updated route on server");
}
} catch (e) {
print("Failed to update route on server");
}
}
Continuation:
// Set the current route variant
_currentRouteVariant = routeVariant;
@@ -135,6 +188,10 @@ class LiveInformation {
]
);
// Display the route variant
announcementModule.queueAnnouncementByRouteVariant(routeVariant: routeVariant);
}
// Public methods
@@ -143,16 +200,329 @@ class LiveInformation {
return _currentRouteVariant;
}
Future<void> setRouteVariant(BusRouteVariant routeVariant) async {
await commandModule.executeCommand(
"setroute ${routeVariant.busRoute.routeNumber} ${routeVariant.busRoute.routeVariants.values.toList().indexOf(routeVariant)}"
Future<void> setRouteVariantQuery(String routeNumber, int routeVariantIndex) async {
BusRoute route = busSequences.routes[routeNumber]!;
BusRouteVariant routeVariant = route.routeVariants.values.toList()[routeVariantIndex];
await setRouteVariant(
routeVariant
);
}
// Multi device support
Future<void> createRoom(String roomCode) async {
print("Creating room with code $roomCode");
// Update the room code
this.roomCode = roomCode;
// Enable host mode
isHost = true;
// Access the database
final client = auth.client;
final databases = appwrite.Databases(client);
// Remove any existing documents
final existingDocuments = await databases.listDocuments(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
queries: [
appwrite.Query.search("SessionID", roomCode)
]
);
for (var document in existingDocuments.documents) {
await databases.deleteDocument(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
documentId: document.$id
);
}
// Create the document
final document = await databases.createDocument(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
documentId: appwrite.ID.unique(),
data: {
"SessionID": roomCode,
"LastUpdater": auth.userID,
}
);
// Listen for changes
// { Breaks due to bug in appwrite
// final realtime = appwrite.Realtime(client);
//
// if (_subscription != null) {
// _subscription!.close();
// }
//
// _subscription = realtime.subscribe(
// ['databases.6633e85400036415ab0f.collections.6633e85d0020f52f3771.documents.${document.$id}']
// );
// _subscription!.stream.listen(ServerListener);
// }
// Listen for changes
if (_keepAliveConnection != null) {
try {
_keepAliveConnection!.close();
} catch (e) {
print("Failed to close connection... oh well");
}
}
String APPWRITE_ENDPOINT_URL = "https://cloud.appwrite.io/v1";
String domain = APPWRITE_ENDPOINT_URL.replaceAll("https://", "").trim();
_keepAliveConnection = RealtimeKeepAliveConnection(
channels: ['databases.6633e85400036415ab0f.collections.6633e85d0020f52f3771.documents.${document.$id}'],
onData: ServerListener,
domain: domain,
client: auth.client,
onError: (e) {
print("Workarround Error: $e");
},
);
_keepAliveConnection!.initialize();
// Update the room document ID
roomDocumentID = document.$id;
print("Created room with code $roomCode");
}
Future<void> JoinRoom(String roomCode) async {
print("Joining room with code $roomCode");
// Disable host mode
isHost = false;
// Update the room code
this.roomCode = roomCode;
// Access the database
final client = auth.client;
final databases = appwrite.Databases(client);
// Get the document
final response = await databases.listDocuments(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
queries: [
appwrite.Query.search("SessionID", roomCode)
]
);
if (response.documents.isEmpty) {
throw Exception("Room not found");
}
final document = response.documents.first;
// Listen for changes
// {
// final realtime = appwrite.Realtime(client);
//
// if (_subscription != null) {
// _subscription!.close();
// }
//
// _subscription = realtime.subscribe([
// 'databases.6633e85400036415ab0f.collections.6633e85d0020f52f3771.documents.${document.$id}'
// ]);
//
// _subscription!.stream.listen(ServerListener);
// }
// Listen for changes
if (_keepAliveConnection != null) {
try {
_keepAliveConnection!.close();
} catch (e) {
print("Failed to close connection... oh well");
}
}
String APPWRITE_ENDPOINT_URL = "https://cloud.appwrite.io/v1";
String domain = APPWRITE_ENDPOINT_URL.replaceAll("https://", "").trim();
_keepAliveConnection = RealtimeKeepAliveConnection(
channels: ['databases.6633e85400036415ab0f.collections.6633e85d0020f52f3771.documents.${document.$id}'],
onData: ServerListener,
domain: domain,
client: auth.client,
onError: (e) {
print("Workarround Error: $e");
},
);
_keepAliveConnection!.initialize();
// Update the room document ID
roomDocumentID = document.$id;
// Get the current route
try {
String routeNumber = document.data["CurrentRoute"];
int routeVariantIndex = document.data["CurrentRouteVariant"];
await setRouteVariantQuery(routeNumber, routeVariantIndex);
print("Set route to $routeNumber $routeVariantIndex");
} catch (e) {
print("Failed to set route");
}
print("Joined room with code $roomCode");
}
String? lastCommand;
Future<void> ServerListener(appwrite.RealtimeMessage response) async {
print("Session update");
// Only do something if the document was created or updated
if (!(response.events.first.contains("create") || response.events.first.contains("update"))) {
return;
}
// Get the user that caused the event
String senderID = response.payload["LastUpdater"];
// If the sender is the same as the client, then ignore the event
if (senderID == auth.userID) {
print("Ignoring event");
return;
}
// Check to see if the commands are updated
try {
// Get the new route
String routeNumber = response.payload["CurrentRoute"];
int routeVariantIndex = response.payload["CurrentRouteVariant"];
// If the route arent the same, then update the route
if (routeNumber != _currentRouteVariant!.busRoute.routeNumber || routeVariantIndex != _currentRouteVariant!.busRoute.routeVariants.values.toList().indexOf(_currentRouteVariant!)) {
// Set the route
await setRouteVariantQuery(routeNumber, routeVariantIndex);
// announce the route
// announcementModule.queueAnnouncementByRouteVariant(routeVariant: _currentRouteVariant!);
}
} catch (e) {
print("Failed to set route");
}
// Execute the command
List<String> commands = response.payload["Commands"].cast<String>();
String? command = commands.last;
if (command == lastCommand) {
return;
}
lastCommand = command;
List<String> commandParts = _splitCommand(command);
String commandName = commandParts[0];
if (commandName == "announce") {
print("Announce command received");
String mode = commandParts[1];
print ("Command: $command");
if (mode == "info") {
print("Announce info command received");
announcementModule.queueAnnounementByInfoIndex(
sendToServer: false,
infoIndex: int.parse(commandParts[2]),
scheduledTime: DateTime.fromMillisecondsSinceEpoch(int.parse(commandParts[3])),
);
} else if (mode == "dest") {
print("Announce dest command received");
String routeNumber = commandParts[2];
int routeVariantIndex = int.parse(commandParts[3]);
announcementModule.queueAnnouncementByRouteVariant(
sendToServer: false,
routeVariant: busSequences.routes[routeNumber]!.routeVariants.values.toList()[routeVariantIndex],
scheduledTime: DateTime.fromMillisecondsSinceEpoch(int.parse(commandParts[4])),
);
} else if (mode == "manual") {
print("Announce manual command received");
final displayText = commandParts[2];
List<String> audioFileNames = commandParts.sublist(3);
try {
if (int.parse(audioFileNames.last) != null) {
audioFileNames.removeLast();
}
} catch (e) {}
DateTime scheduledTime = LiveInformation().syncedTimeModule.Now().add(Duration(seconds: 1));
try {
if (int.parse(commandParts.last) != null) {
scheduledTime = DateTime.fromMillisecondsSinceEpoch(int.parse(commandParts.last));
}
} catch (e) {}
announcementModule.queueAnnounceByAudioName(
displayText: displayText,
audioNames: audioFileNames,
scheduledTime: scheduledTime,
sendToServer: false
);
}
}
}
String _extractId(String input) {
RegExp regExp = RegExp(r'\("user:(.*)"\)');
Match match = regExp.firstMatch(input)!;
return match.group(1)!;
}
Future<void> SendCommand(String command) async {
final client = auth.client;
final databases = appwrite.Databases(client);
final response = await databases.listDocuments(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
queries: [
appwrite.Query.search("SessionID", roomCode!)
]
);
List<String> pastCommands = [];
response.documents.first.data["Commands"].forEach((element) {
pastCommands.add(element);
});
pastCommands.add(command);
final document = await databases.updateDocument(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
documentId: roomDocumentID!,
data: {
"Commands": pastCommands,
"LastUpdater": auth.userID,
}
);
}
List<String> _splitCommand(String command) {
var regex = RegExp(r'([^\s"]+)|"([^"]*)"');
var matches = regex.allMatches(command);
return matches.map((match) => match.group(0)!.replaceAll('"', '')).toList();
}
@@ -162,8 +532,6 @@ class LiveInformation {
}
class AnnouncementQueueEntry {

View File

@@ -74,7 +74,7 @@ class AnnouncementModule extends InfoModule {
final EventDelegate<AnnouncementQueueEntry> onAnnouncement = EventDelegate();
// Timer
Timer refreshTimer() => Timer.periodic(const Duration(milliseconds: 200), (timer) async {
Timer refreshTimer() => Timer.periodic(const Duration(milliseconds: 10), (timer) async {
if (!isPlaying) {
@@ -84,7 +84,7 @@ class AnnouncementModule extends InfoModule {
bool proceeding = await _internalAccountForInconsistentTime(
announcement: nextAnnouncement,
timerInterval: const Duration(milliseconds: 200),
timerInterval: const Duration(milliseconds: 10),
callback: () {
queue.removeAt(0);
print("Announcement proceeding");
@@ -105,35 +105,21 @@ class AnnouncementModule extends InfoModule {
if (currentAnnouncement!.audioSources.isNotEmpty) {
// audioPlayer.loadSource(AudioWrapperAssetSource("assets/audio/5-seconds-of-silence.mp3"));
// audioPlayer.play();
// await Future.delayed(const Duration(milliseconds: 300));
// audioPlayer.stop();
// Prime all of the audio sources to be ready to play
for (AudioWrapperSource source in currentAnnouncement!.audioSources) {
try {
await audioPlayer.loadSource(source);
await Future.delayed((await audioPlayer.play())!);
audioPlayer.stop();
// try {
for (AudioWrapperSource source in currentAnnouncement!.audioSources) {
try {
await audioPlayer.loadSource(source);
Duration? duration = await audioPlayer.play();
await Future.delayed(duration!);
audioPlayer.stop();
// await Future.delayed(const Duration(milliseconds: 100));
if (currentAnnouncement?.audioSources.last != source) {
await Future.delayed(const Duration(milliseconds: 100));
}
} catch (e) {
// Do nothing
// print("Error playing announcement: $e on ${currentAnnouncement?.displayText}");
await Future.delayed(const Duration(seconds: 1));
if (currentAnnouncement?.audioSources.last != source) {
await Future.delayed(const Duration(milliseconds: 100));
}
} catch (e) {
await Future.delayed(const Duration(seconds: 1));
}
// audioPlayer.stop();
}
// } catch (e) {
// // Do nothing
// print("Error playing announcement: $e on ${currentAnnouncement?.displayTex}");
// }
} else {
if (queue.isNotEmpty) {
await Future.delayed(const Duration(seconds: 5));
@@ -179,7 +165,7 @@ class AnnouncementModule extends InfoModule {
}
// Configuration
int get defaultAnnouncementDelay => liveInformation.auth.isAuthenticated() ? 2 : 0;
int get defaultAnnouncementDelay => liveInformation.auth.isAuthenticated() ? 1 : 0;
// Methods
Future<void> queueAnnounceByAudioName({
@@ -199,8 +185,12 @@ class AnnouncementModule extends InfoModule {
audioNamesString += "\"$audioName\" ";
}
liveInformation.commandModule.executeCommand(
"announce manual \"$displayText\" ${audioNamesString} ${scheduledTime?.millisecondsSinceEpoch ?? ""}"
liveInformation.SendCommand("announce manual \"$displayText\" $audioNamesString ${scheduledTime.millisecondsSinceEpoch}");
queueAnnounceByAudioName(
displayText: displayText,
audioNames: audioNames,
scheduledTime: scheduledTime,
sendToServer: false
);
return;
@@ -244,9 +234,13 @@ class AnnouncementModule extends InfoModule {
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
liveInformation.commandModule.executeCommand(
"announce info $infoIndex ${scheduledTime?.millisecondsSinceEpoch ?? ""}"
liveInformation.SendCommand("announce info $infoIndex ${scheduledTime.millisecondsSinceEpoch}");
queueAnnounementByInfoIndex(
infoIndex: infoIndex,
scheduledTime: scheduledTime,
sendToServer: false
);
print("Announcement sent to server");
return;
}
@@ -270,9 +264,16 @@ class AnnouncementModule extends InfoModule {
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
liveInformation.commandModule.executeCommand(
"announce dest \"${routeVariant.busRoute.routeNumber}\" ${routeVariant.busRoute.routeVariants.values.toList().indexOf(routeVariant)} ${scheduledTime?.millisecondsSinceEpoch ?? ""}"
String routeNumber = routeVariant.busRoute.routeNumber;
int routeVariantIndex = routeVariant.busRoute.routeVariants.values.toList().indexOf(routeVariant);
liveInformation.SendCommand("announce dest ${routeNumber} ${routeVariantIndex} ${scheduledTime.millisecondsSinceEpoch}");
queueAnnouncementByRouteVariant(
routeVariant: routeVariant,
scheduledTime: scheduledTime,
sendToServer: false
);
return;
}
print("Checkpoint 4");

View File

@@ -47,17 +47,37 @@ class CommandModule extends InfoModule {
final databases = appwrite.Databases(client);
if (liveInformation.auth.status == AuthStatus.AUTHENTICATED) {
final document = await databases.createDocument(
databaseId: ApiConstants.INFO_Q_DATABASE_ID,
collectionId: ApiConstants.COMMANDS_COLLECTION_ID,
documentId: appwrite.ID.unique(),
if (true) {
try {
final response = await databases.listDocuments(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
queries: [
appwrite.Query.search("SessionID", liveInformation.roomCode!)
]
);
List<String> pastCommands = [];
response.documents.first.data["Commands"].forEach((element) {
pastCommands.add(element);
});
pastCommands.add(command);
final document = await databases.updateDocument(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
documentId: liveInformation.roomDocumentID!,
data: {
"session_id": sessionID,
"command": command,
"client_id": clientID,
"Commands": pastCommands,
"LastUpdater": clientID,
}
);
);
} catch (e) {
print("Failed to send command");
}
}
_onCommandReceived(CommandInfo(command, clientID));
@@ -78,6 +98,10 @@ class CommandModule extends InfoModule {
if (command == "Response:") {
}
else if (command == "initroom") {
// initroom <roomCode>
}
else if (command == "announce") {
@@ -166,10 +190,41 @@ class CommandModule extends InfoModule {
BusRoute route = liveInformation.busSequences.routes[routeNumber]!;
BusRouteVariant routeVariant = route.routeVariants.values.toList()[routeVariantIndex];
liveInformation.setRouteVariant_Internal(
liveInformation.setRouteVariant(
routeVariant
);
executeCommand("Response: v \"Client $clientID set its route to ($routeNumber to ${routeVariant.busStops.last.formattedStopName})\"");
// Update the server
if (liveInformation.isHost) {
print("Updating server");
final client = liveInformation.auth.client;
final databases = appwrite.Databases(client);
final response = await databases.listDocuments(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
queries: [
appwrite.Query.search("SessionID", liveInformation.roomCode!)
]
);
final document = await databases.updateDocument(
databaseId: "6633e85400036415ab0f",
collectionId: "6633e85d0020f52f3771",
documentId: response.documents.first.$id,
data: {
"CurrentRoute": routeNumber,
"CurrentRouteVariant": routeVariantIndex,
}
);
try {
print("Updated server");
} catch (e) {
print("Failed to update server");
}
}
}
@@ -181,26 +236,26 @@ class CommandModule extends InfoModule {
return;
}
final realtime = appwrite.Realtime(LiveInformation().auth.client);
_subscription = realtime.subscribe(
['databases.${ApiConstants.INFO_Q_DATABASE_ID}.collections.${ApiConstants.COMMANDS_COLLECTION_ID}.documents']
);
_subscription!.stream.listen((event) {
print(jsonEncode(event.payload));
// Only do something if the document was created or updated
if (!(event.events.first.contains("create") || event.events.first.contains("update"))) {
return;
}
final commandInfo = CommandInfo(event.payload['command'], event.payload['client_id']);
if (commandInfo.clientID != clientID) {
_onCommandReceived(commandInfo);
}
});
// final realtime = appwrite.Realtime(LiveInformation().auth.client);
//
// _subscription = realtime.subscribe(
// ['databases.${ApiConstants.INFO_Q_DATABASE_ID}.collections.${ApiConstants.COMMANDS_COLLECTION_ID}.documents']
// );
// _subscription!.stream.listen((event) {
// print(jsonEncode(event.payload));
//
// // Only do something if the document was created or updated
// if (!(event.events.first.contains("create") || event.events.first.contains("update"))) {
// return;
// }
//
// final commandInfo = CommandInfo(event.payload['command'], event.payload['client_id']);
//
// if (commandInfo.clientID != clientID) {
// _onCommandReceived(commandInfo);
// }
//
// });
print("Listening for commands");

View File

@@ -183,7 +183,6 @@ class TrackerModule extends InfoModule {
print("Closest stop: ${closestStop.formattedStopName} in ${closestDistance.round()} meters");
}
}
double _calculateRelativeDistance(BusRouteStop stop, double latitude, double longitude) {

View File

@@ -68,7 +68,7 @@ class TubeStations {
double distance = Vector2(stop.easting.toDouble(), stop.northing.toDouble()).distanceTo(OSGrid.toNorthingEasting(station.latitude, station.longitude));
// if the distance is less than 100m, then we can assume that the bus stop is near the tube station
if (distance < 200) {
if (distance < 400) {
for (TubeLine line in station.lines) {
lineMatches[line] = lineMatches[line]! + 1;
}

View File

@@ -11,6 +11,7 @@ import 'package:bus_infotainment/utils/delegates.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
class pages_Home extends StatelessWidget {
const pages_Home({super.key});
@@ -60,7 +61,7 @@ class pages_Home extends StatelessWidget {
outlineColor: Colors.white70,
announcements: [
for (NamedAnnouncementQueueEntry announcement in LiveInformation().announcementModule.manualAnnouncements)
_AnnouncementEntry(
AnnouncementEntry(
label: announcement.shortName,
index: LiveInformation().announcementModule.manualAnnouncements.indexOf(announcement),
outlineColor: Colors.white70,
@@ -92,12 +93,12 @@ class pages_Home extends StatelessWidget {
color: Colors.grey.shade900,
),
child: DelegateBuilder<BusRouteVariant>(
child: DelegateBuilder<BusRouteVariant?>(
delegate: LiveInformation().routeVariantDelegate,
builder: (context, routeVariant) {
print("rebuilt stop announcement picker");
return StopAnnouncementPicker(
routeVariant: routeVariant,
routeVariant: routeVariant!,
backgroundColor: Colors.grey.shade900,
outlineColor: Colors.white70,
);
@@ -133,11 +134,6 @@ class pages_Home extends StatelessWidget {
ElevatedButton(
onPressed: () async {
LiveInformation liveInformation = LiveInformation();
final commandModule = liveInformation.commandModule;
// commandModule.executeCommand(
// "announce dest"
// );
liveInformation.announcementModule.queueAnnouncementByRouteVariant(
routeVariant: liveInformation.getRouteVariant()!
@@ -147,75 +143,7 @@ class pages_Home extends StatelessWidget {
child: Text("Announce current destination"),
),
// Container(
//
// margin: EdgeInsets.all(20),
//
// height: 300-45,
//
// child: ListView(
//
// scrollDirection: Axis.vertical,
//
// children: [
//
// ElevatedButton(
// onPressed: () async {
// LiveInformation liveInformation = LiveInformation();
// liveInformation.queueAnnouncement(await liveInformation.getDestinationAnnouncement(liveInformation.getRouteVariant()!, sendToServer: false));
// },
// child: Text("Test announcement"),
// ),
//
// ElevatedButton(
// onPressed: () {
// LiveInformation liveInformation = LiveInformation();
// liveInformation.updateServer();
// },
// child: Text("Update server"),
// ),
//
// SizedBox(
//
// width: 100,
//
// child: TextField(
// onChanged: (String value) {
// LiveInformation liveInformation = LiveInformation();
// // liveInformation.documentID = value;
// },
// ),
// ),
//
// SizedBox(
//
// width: 200,
//
// child: TextField(
// onSubmitted: (String value) {
// LiveInformation liveInformation = LiveInformation();
// liveInformation.queueAnnouncement(AnnouncementQueueEntry(
// displayText: value,
// audioSources: []
// ));
// },
// ),
// ),
//
// ElevatedButton(
// onPressed: () {
// LiveInformation liveInformation = LiveInformation();
// liveInformation.pullServer();
// },
// child: Text("Pull server"),
// ),
//
// ],
//
// ),
//
// ),
],
),
@@ -366,8 +294,9 @@ class AnnouncementPicker extends StatefulWidget {
final Color backgroundColor;
final Color outlineColor;
final List<Widget> announcements;
final String label;
const AnnouncementPicker({super.key, required this.backgroundColor, required this.outlineColor, required this.announcements});
const AnnouncementPicker({super.key, required this.backgroundColor, required this.outlineColor, required this.announcements, this.label = ""});
@override
State<AnnouncementPicker> createState() => _AnnouncementPickerState();
@@ -411,9 +340,9 @@ class _AnnouncementPickerState extends State<AnnouncementPicker> {
color: widget.backgroundColor,
border: Border.all(
color: widget.outlineColor,
width: 2
width: 1
),
borderRadius: BorderRadius.circular(8)
),
@@ -428,118 +357,26 @@ class _AnnouncementPickerState extends State<AnnouncementPicker> {
child: Column(
children: [
Container(
height: 2,
color: widget.outlineColor,
),
if (_currentIndex < announcementWidgets.length)
announcementWidgets[_currentIndex + 0]
else
Container(
height: 50,
decoration: BoxDecoration(
color: widget.backgroundColor,
border: Border.symmetric(
vertical: BorderSide(
color: widget.outlineColor,
width: 2
)
),
),
),
Container(
height: 2,
color: widget.outlineColor,
),
if (_currentIndex + 1 < announcementWidgets.length)
announcementWidgets[_currentIndex + 1]
else
Container(
height: 50,
decoration: BoxDecoration(
color: widget.backgroundColor,
border: Border.symmetric(
vertical: BorderSide(
color: widget.outlineColor,
width: 2
)
),
),
),
Container(
height: 2,
color: widget.outlineColor,
),
if (_currentIndex + 2 < announcementWidgets.length)
announcementWidgets[_currentIndex + 2]
else
Container(
height: 50,
decoration: BoxDecoration(
color: widget.backgroundColor,
border: Border.symmetric(
vertical: BorderSide(
color: widget.outlineColor,
width: 2
)
),
),
),
Container(
height: 2,
color: widget.outlineColor,
),
if (_currentIndex + 3 < announcementWidgets.length)
announcementWidgets[_currentIndex + 3]
else
Container(
height: 50,
decoration: BoxDecoration(
color: widget.backgroundColor,
border: Border.symmetric(
vertical: BorderSide(
color: widget.outlineColor,
width: 2
)
),
),
),
Container(
height: 2,
color: widget.outlineColor,
),
Container(
height: 40,
decoration: BoxDecoration(
color: widget.backgroundColor,
border: Border.symmetric(
vertical: BorderSide(
color: widget.outlineColor,
width: 2
)
border: Border.all(
color: widget.outlineColor,
width: 1
),
borderRadius: BorderRadius.circular(4)
),
alignment: Alignment.centerRight,
child: Row(
mainAxisSize: MainAxisSize.min,
// height: 100,
child: Column(
children: [
Container(
width: 40,
height: 40,
if (_currentIndex < announcementWidgets.length)
announcementWidgets[_currentIndex + 0]
else
Container(
height: 50,
decoration: BoxDecoration(
color: widget.backgroundColor,
border: Border.symmetric(
@@ -549,50 +386,18 @@ class _AnnouncementPickerState extends State<AnnouncementPicker> {
)
),
),
margin: const EdgeInsets.symmetric(
horizontal: 4
),
child: Container(
child: Stack(
children: [
Container(
width: 40,
height: 40,
child: Icon(
Icons.arrow_upward,
color: widget.outlineColor,
),
),
Positioned.fill(
child: ElevatedButton(
onPressed: () {
_currentIndex = wrap(_currentIndex - 4, 0, announcementWidgets.length, increment: 4);
setState(() {});
print(_currentIndex);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
foregroundColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
),
child: const Text(""),
),
)
],
),
)
),
),
Container(
width: 40,
height: 40,
height: 1,
color: widget.outlineColor,
),
if (_currentIndex + 1 < announcementWidgets.length)
announcementWidgets[_currentIndex + 1]
else
Container(
height: 50,
decoration: BoxDecoration(
color: widget.backgroundColor,
border: Border.symmetric(
@@ -602,55 +407,200 @@ class _AnnouncementPickerState extends State<AnnouncementPicker> {
)
),
),
),
margin: const EdgeInsets.symmetric(
horizontal: 4
),
child: Container(
child: Stack(
children: [
Container(
width: 40,
height: 40,
child: Icon(
Icons.arrow_downward,
color: widget.outlineColor,
),
),
Positioned.fill(
child: ElevatedButton(
onPressed: () {
_currentIndex = wrap(_currentIndex + 4, 0, announcementWidgets.length, increment: 4);
setState(() {});
print(_currentIndex);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
foregroundColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
),
child: const Text(""),
),
)
],
),
)
Container(
height: 1,
color: widget.outlineColor,
),
]
if (_currentIndex + 2 < announcementWidgets.length)
announcementWidgets[_currentIndex + 2]
else
Container(
height: 50,
decoration: BoxDecoration(
color: widget.backgroundColor,
border: Border.symmetric(
vertical: BorderSide(
color: widget.outlineColor,
width: 2
)
),
),
),
Container(
height: 1,
color: widget.outlineColor,
),
if (_currentIndex + 3 < announcementWidgets.length)
announcementWidgets[_currentIndex + 3]
else
Container(
height: 50,
decoration: BoxDecoration(
color: widget.backgroundColor,
border: Border.symmetric(
vertical: BorderSide(
color: widget.outlineColor,
width: 2
)
),
),
),
Container(
height: 1,
color: widget.outlineColor,
),
Container(
height: 40,
decoration: BoxDecoration(
color: widget.backgroundColor,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.symmetric(
horizontal: 8,
),
child: Text(
widget.label,
style: ShadTheme.of(context).textTheme.h4.copyWith(
shadows: [
Shadow(
color: Colors.blueAccent.shade700,
blurRadius: 8
)
],
color: Colors.blueAccent.shade700
)
),
),
Expanded(child: Container()),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: widget.backgroundColor,
border: Border.symmetric(
vertical: BorderSide(
color: widget.outlineColor,
width: 1
)
),
),
margin: const EdgeInsets.symmetric(
horizontal: 4
),
child: Container(
child: Stack(
children: [
Container(
width: 40,
height: 40,
child: Icon(
Icons.arrow_upward,
color: widget.outlineColor,
),
),
Positioned.fill(
child: ElevatedButton(
onPressed: () {
_currentIndex = wrap(_currentIndex - 4, 0, announcementWidgets.length, increment: 4);
setState(() {});
print(_currentIndex);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
foregroundColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
),
child: const Text(""),
),
)
],
),
)
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: widget.backgroundColor,
border: Border.symmetric(
vertical: BorderSide(
color: widget.outlineColor,
width: 1
)
),
),
margin: const EdgeInsets.symmetric(
horizontal: 4
),
child: Container(
child: Stack(
children: [
Container(
width: 40,
height: 40,
child: Icon(
Icons.arrow_downward,
color: widget.outlineColor,
),
),
Positioned.fill(
child: ElevatedButton(
onPressed: () {
_currentIndex = wrap(_currentIndex + 4, 0, announcementWidgets.length, increment: 4);
setState(() {});
print(_currentIndex);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
foregroundColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
),
child: const Text(""),
),
)
],
),
)
),
]
),
),
],
),
),
Container(
height: 2,
color: widget.outlineColor,
),
]
@@ -669,13 +619,14 @@ class StopAnnouncementPicker extends AnnouncementPicker {
required this.routeVariant,
required Color backgroundColor,
required Color outlineColor,
String label = "Stops"
}) : super(
key: key,
backgroundColor: backgroundColor,
outlineColor: outlineColor,
announcements: [
for (BusRouteStop stop in routeVariant.busStops)
_AnnouncementEntry(
AnnouncementEntry(
label: stop.formattedStopName,
onPressed: () {
LiveInformation liveInformation = LiveInformation();
@@ -688,7 +639,8 @@ class StopAnnouncementPicker extends AnnouncementPicker {
outlineColor: outlineColor,
alert: LiveInformation().announcementModule.announcementCache[stop.getAudioFileName()] == null,
)
]
],
label: label
);
}
@@ -709,7 +661,7 @@ int wrap(int i, int j, int length, {int increment = -1}) {
}
}
class _AnnouncementEntry extends StatelessWidget {
class AnnouncementEntry extends StatelessWidget {
final String label;
@@ -719,7 +671,7 @@ class _AnnouncementEntry extends StatelessWidget {
bool alert = false;
_AnnouncementEntry({super.key, required this.label, required this.onPressed, required this.index, required this.outlineColor, this.alert = false});
AnnouncementEntry({super.key, required this.label, required this.onPressed, required this.index, required this.outlineColor, this.alert = false});
@override
Widget build(BuildContext context) {
@@ -730,12 +682,6 @@ class _AnnouncementEntry extends StatelessWidget {
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.symmetric(
vertical: BorderSide(
color: outlineColor,
width: 2
)
),
),
padding: const EdgeInsets.symmetric(
@@ -760,7 +706,7 @@ class _AnnouncementEntry extends StatelessWidget {
label,
style: GoogleFonts.teko(
fontSize: 25,
color: outlineColor,
color: Colors.white,
),
overflow: TextOverflow.ellipsis,
),

View File

@@ -1228,11 +1228,11 @@ class _ConsoleState extends State<Console> {
// TODO: implement initState
super.initState();
_listenerReceipt = LiveInformation().commandModule.onCommandReceived.addListener((p0) {
/*_listenerReceipt = LiveInformation().commandModule.onCommandReceived.addListener((p0) {
print("Command received, updating console");
setState(() {});
});
});*/
}
@@ -1253,7 +1253,7 @@ class _ConsoleState extends State<Console> {
Text("Command History:")
);
for (int i = 0; i < LiveInformation().commandModule.commandHistory.length; i++){
/*for (int i = 0; i < LiveInformation().commandModule.commandHistory.length; i++){
CommandInfo command = LiveInformation().commandModule.commandHistory[i];
commands.add(
@@ -1271,7 +1271,7 @@ class _ConsoleState extends State<Console> {
)
);
}
*/
return Container(
decoration: BoxDecoration(
@@ -1299,7 +1299,7 @@ class _ConsoleState extends State<Console> {
color: Colors.white70,
),
Container(
/*Container(
height: 50,
padding: const EdgeInsets.all(8),
child: TextField(
@@ -1315,7 +1315,7 @@ class _ConsoleState extends State<Console> {
LiveInformation().commandModule.executeCommand(value);
},
),
)
)*/
],

View File

@@ -1,6 +1,7 @@
import 'package:bus_infotainment/pages/tfl_dataset_test.dart';
import 'package:bus_infotainment/remaster/InitialStartup.dart';
import 'package:bus_infotainment/remaster/dashboard.dart';
import 'package:flutter/material.dart';
@@ -15,13 +16,22 @@ class RemasteredApp extends StatelessWidget {
darkTheme: ShadThemeData(
brightness: Brightness.dark,
colorScheme: ShadSlateColorScheme.dark(),
// force dark mode
),
themeMode: ThemeMode.dark,
routes: {
'/setup': (context) => InitialStartup(),
'/': (context) => HomePage_Re(),
'/routes': (context) => RoutePage(),
'/enroute': (context) => EnRoutePage(),
'/legacy': (context) => TfL_Dataset_Test(),
'/multi': (context) => MultiModeSetup(),
'/multi/enroute': (context) => MultiModeEnroute(),
'/multi/login': (context) => MultiModeLogin(),
'/multi/register': (context) => MultiModeRegister(),
'/display': (context) => FullscreenDisplay(),
'/multi/join': (context) => MultiModeJoin(),
},

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,112 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:appwrite/appwrite.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
// import this package https://pub.dev/packages/web_socket_channel
class RealtimeKeepAliveConnection {
RealtimeKeepAliveConnection({
required this.channels,
required this.domain,
required this.client,
this.keepAlivePingDuration = const Duration(seconds: 90),
required this.onData,
required this.onError,
});
final List<String> channels;
final String domain;
final Duration keepAlivePingDuration;
final Client client;
final Function(RealtimeMessage) onData;
final Function(dynamic) onError;
// ignore: unused_field
StreamSubscription<dynamic>? _subscription;
WebSocketChannel? _webSocket;
final Stopwatch _stopwatch = Stopwatch();
bool _keepAlive = true;
bool _sentKeepAlivePing = false;
int reconnectCount = 0;
Future initialize() async {
await _initRealtime(
onData: _realtimeOnData,
onDone: _realtimeOnDone,
onError: _realtimeOnError,
);
_heartbeat();
}
void close() {
_keepAlive = false;
_subscription!.cancel();
}
void _heartbeat() async {
while (_keepAlive) {
await Future.delayed(keepAlivePingDuration);
if (_webSocket != null) {
_sentKeepAlivePing = true;
_webSocket!.sink.add("ping");
}
}
}
void _realtimeOnData(RealtimeMessage data) {
log("[$reconnectCount][${_stopwatch.elapsed}] onData");
onData(data);
}
void _realtimeOnDone() async {
reconnectCount++;
log("[$reconnectCount][${_stopwatch.elapsed}] onDone");
if (_keepAlive) {
if (_subscription != null) _subscription!.cancel();
_subscription = _subscription = await _initRealtime(
onData: _realtimeOnData,
onDone: _realtimeOnDone,
onError: _realtimeOnError,
);
}
}
void _realtimeOnError(dynamic e) {
log("[$reconnectCount][${_stopwatch.elapsed}] onError:$e");
onError(onError);
}
Future _initRealtime({
required Function(RealtimeMessage) onData,
required Function() onDone,
required Function(dynamic) onError,
}) async {
_stopwatch.reset();
_stopwatch.start();
String channelParams = channels.map((c) => "channels[]=$c").join('&');
String? projectId = client.config['project'];
final wssUrl = Uri.parse('wss://$domain/realtime?project=$projectId&$channelParams');
_webSocket = WebSocketChannel.connect(wssUrl);
Realtime realtime = Realtime(client);
RealtimeSubscription subscriptionRealTime = realtime.subscribe(channels);
subscriptionRealTime.stream.listen(onData, onDone: onDone, onError: onError);
_subscription = _webSocket!.stream.listen(_handlePingMsg);
}
void _handlePingMsg(dynamic response) {
var json = jsonDecode(response);
if (json["type"] == "error" && _sentKeepAlivePing) {
_sentKeepAlivePing = false;
log("Web socket keep-alive heartbeat successful (Reconnect Count: $reconnectCount, Time alive: ${_stopwatch.elapsed})");
return;
}
}
}

View File

@@ -185,6 +185,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.8"
dart_ping:
dependency: "direct main"
description:
name: dart_ping
sha256: "2f5418d0a5c64e53486caaac78677b25725b1e13c33c5be834ce874ea18bd24f"
url: "https://pub.dev"
source: hosted
version: "9.0.1"
device_info_plus:
dependency: transitive
description:
@@ -565,6 +573,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
native_qr:
dependency: "direct main"
description:
name: native_qr
sha256: "0928754b92305eb101a3359014a60ac5e90126534406b4dd6fb7550433978420"
url: "https://pub.dev"
source: hosted
version: "0.0.3"
ntp:
dependency: "direct main"
description:
@@ -741,6 +757,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.0"
qr:
dependency: transitive
description:
name: qr
sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
qr_flutter:
dependency: "direct main"
description:
name: qr_flutter
sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097"
url: "https://pub.dev"
source: hosted
version: "4.1.0"
rive:
dependency: transitive
description:

View File

@@ -52,6 +52,9 @@ dependencies:
file_picker: ^8.0.0+1
shadcn_ui: ^0.4.1
flutter_carousel_widget: ^2.2.0
dart_ping: ^9.0.1
native_qr: ^0.0.3
qr_flutter: ^4.1.0
# The following adds the Cupertino Icons font to your application.