From 445acb5da5ba9e321a016630d58147c7e69fe916 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 21 May 2022 14:09:26 -0700 Subject: Initialize device location --- tools/test-map.py | 1 + 1 file changed, 1 insertion(+) (limited to 'tools') diff --git a/tools/test-map.py b/tools/test-map.py index c289df605..ab4466b09 100755 --- a/tools/test-map.py +++ b/tools/test-map.py @@ -38,6 +38,7 @@ conn = httplib.HTTPConnection(server) for i in range(devices): device_id = "{0:0>6}".format(i) add_device(cookie, device_id) + send_message(conn, device_id) while True: device_id = "{0:0>6}".format(random.randint(0, devices)) -- cgit v1.2.3 From c49bda5396847731f4eea8f6e3f0e0dd6811ae6f Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 3 Jul 2022 15:52:39 -0700 Subject: Support KML export (fix #1858, fix #2329) --- .../org/traccar/api/resource/PositionResource.java | 21 ++++++ .../org/traccar/reports/KmlExportProvider.java | 80 ++++++++++++++++++++++ tools/test-generator.py | 7 +- 3 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/traccar/reports/KmlExportProvider.java (limited to 'tools') diff --git a/src/main/java/org/traccar/api/resource/PositionResource.java b/src/main/java/org/traccar/api/resource/PositionResource.java index cac64feb1..28f8eb600 100644 --- a/src/main/java/org/traccar/api/resource/PositionResource.java +++ b/src/main/java/org/traccar/api/resource/PositionResource.java @@ -20,17 +20,22 @@ import org.traccar.helper.model.PositionUtil; import org.traccar.model.Device; import org.traccar.model.Position; import org.traccar.model.UserRestrictions; +import org.traccar.reports.KmlExportProvider; import org.traccar.storage.StorageException; import org.traccar.storage.query.Columns; import org.traccar.storage.query.Condition; import org.traccar.storage.query.Request; +import javax.inject.Inject; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -41,6 +46,9 @@ import java.util.List; @Consumes(MediaType.APPLICATION_JSON) public class PositionResource extends BaseResource { + @Inject + private KmlExportProvider kmlExportProvider; + @GET public Collection getJson( @QueryParam("deviceId") long deviceId, @QueryParam("id") List positionIds, @@ -69,4 +77,17 @@ public class PositionResource extends BaseResource { } } + @Path("kml") + @GET + @Produces("application/vnd.google-earth.kml+xml") + public Response getKml( + @QueryParam("deviceId") long deviceId, + @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { + permissionsService.checkPermission(Device.class, getUserId(), deviceId); + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + kmlExportProvider.generateKml(stream, deviceId, from, to); + return Response.ok(stream.toByteArray()) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=positions.kml").build(); + } + } diff --git a/src/main/java/org/traccar/reports/KmlExportProvider.java b/src/main/java/org/traccar/reports/KmlExportProvider.java new file mode 100644 index 000000000..977897833 --- /dev/null +++ b/src/main/java/org/traccar/reports/KmlExportProvider.java @@ -0,0 +1,80 @@ +/* + * Copyright 2022 Anton Tananaev (anton@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.reports; + +import org.traccar.helper.model.PositionUtil; +import org.traccar.model.Device; +import org.traccar.storage.Storage; +import org.traccar.storage.StorageException; +import org.traccar.storage.query.Columns; +import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Request; + +import javax.inject.Inject; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.stream.Collectors; + +public class KmlExportProvider { + + private final Storage storage; + + @Inject + public KmlExportProvider(Storage storage) { + this.storage = storage; + } + + public void generateKml( + OutputStream outputStream, long deviceId, Date from, Date to) throws StorageException { + + var device = storage.getObject(Device.class, new Request( + new Columns.All(), new Condition.Equals("id", "id", deviceId))); + var positions = PositionUtil.getPositions(storage, deviceId, from, to); + + var dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + try (PrintWriter writer = new PrintWriter(outputStream)) { + writer.print(""); + writer.print(""); + writer.print(""); + writer.print(""); + writer.print(device.getName()); + writer.print(""); + writer.print(""); + writer.print(""); + writer.print(dateFormat.format(from)); + writer.print(" - "); + writer.print(dateFormat.format(to)); + writer.print(""); + writer.print(""); + writer.print("1"); + writer.print("1"); + writer.print("absolute"); + writer.print(""); + writer.print(positions.stream() + .map((p -> String.format("%f,%f,%f", p.getLongitude(), p.getLatitude(), p.getAltitude()))) + .collect(Collectors.joining(" "))); + writer.print(""); + writer.print(""); + writer.print(""); + writer.print(""); + writer.print(""); + } + } + +} diff --git a/tools/test-generator.py b/tools/test-generator.py index b8a06ac32..eb50d2600 100755 --- a/tools/test-generator.py +++ b/tools/test-generator.py @@ -35,8 +35,8 @@ for i in range(0, len(waypoints)): lon = lon1 + (lon2 - lon1) * j / count points.append((lat, lon)) -def send(conn, lat, lon, course, speed, battery, alarm, ignition, accuracy, rpm, fuel, driverUniqueId): - params = (('id', id), ('timestamp', int(time.time())), ('lat', lat), ('lon', lon), ('bearing', course), ('speed', speed), ('batt', battery)) +def send(conn, lat, lon, altitude, course, speed, battery, alarm, ignition, accuracy, rpm, fuel, driverUniqueId): + params = (('id', id), ('timestamp', int(time.time())), ('lat', lat), ('lon', lon), ('altitude', altitude), ('bearing', course), ('speed', speed), ('batt', battery)) if alarm: params = params + (('alarm', 'sos'),) if ignition: @@ -70,6 +70,7 @@ conn = httplib.HTTPConnection(server) while True: (lat1, lon1) = points[index % len(points)] (lat2, lon2) = points[(index + 1) % len(points)] + altitude = 50 speed = device_speed if (index % len(points)) != 0 else 0 alarm = (index % 10) == 0 battery = random.randint(0, 100) @@ -78,6 +79,6 @@ while True: rpm = random.randint(500, 4000) fuel = random.randint(0, 80) driverUniqueId = driver_id if (index % len(points)) == 0 else False - send(conn, lat1, lon1, course(lat1, lon1, lat2, lon2), speed, battery, alarm, ignition, accuracy, rpm, fuel, driverUniqueId) + send(conn, lat1, lon1, altitude, course(lat1, lon1, lat2, lon2), speed, battery, alarm, ignition, accuracy, rpm, fuel, driverUniqueId) time.sleep(period) index += 1 -- cgit v1.2.3 From 80b3af98806f9e837f65e8074882a97b22d65427 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 9 Jul 2022 16:13:23 -0700 Subject: Sequence integration tests --- tools/test-integration.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/test-integration.py b/tools/test-integration.py index 6251b0d97..e49648cb6 100755 --- a/tools/test-integration.py +++ b/tools/test-integration.py @@ -142,7 +142,7 @@ def send_message(port, message): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', port)) s.send(message) - time.sleep(5) + time.sleep(0.5) s.close() def get_protocols(cookie, device_id): @@ -178,14 +178,8 @@ if __name__ == "__main__": print 'Missing: %d' % len(all - protocols) print 'Covered: %d' % len(protocols) - #if all - protocols: - # print '\nMissing: %s\n' % repr(list((all - protocols))) - for protocol in messages: - thread = threading.Thread(target = send_message, args = (ports[protocol], messages[protocol])) - thread.start() - - time.sleep(10) + send_message(ports[protocol], messages[protocol]) for device in devices: protocols -= set(get_protocols(cookie, devices[device])) -- cgit v1.2.3 From 92807c47464a840999716d2e732f569351deaea0 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 13 Jul 2022 20:41:20 -0700 Subject: Add more integration tests --- tools/test-integration.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'tools') diff --git a/tools/test-integration.py b/tools/test-integration.py index e49648cb6..42922147e 100755 --- a/tools/test-integration.py +++ b/tools/test-integration.py @@ -90,6 +90,15 @@ messages = { 'starlink' : '$SLU123456,06,622,170329035057,01,170329035057,+3158.0018,+03446.6968,004.9,007,000099,1,1,0,0,0,0,0,0,,,14.176,03.826,,1,1,1,4*B0\r\n', 'alematics' : '$T,50,592,123456789012345,20170515062915,20170515062915,25.035005,121.561555,0,31,89,3.7,5,1,0,0.000,12.752,1629,38,12752,4203,6\r\n', 'vtfms' : '(123456789012345,00I76,00,000,,,,,A,133755,210617,10.57354,077.24912,SW,000,00598,00000,K,0017368,1,12.7,,,0.000,,,0,0,0,0,1,1,0,,)074' + 'esky': 'ET;0;123456789012345;R;6+190317162511+41.32536+19.83144+0.14+0+0x0+0+18460312+0+1233+192', + 'genx': '123456789012345,08/31/2017 17:24:13,45.47275,-73.65491,5,19,117,1.14,147,ON,1462,0,6,N,0,0.000,-95.0,-1.0,0,0.0000,0.0000,0.000,0,0.00,0.00,0.00,NA,U,UUU,0,-95.0,U\r\n', + 'dway': 'AA55,115,1234,1,171024,195059,28.0153,-82.4761,3, 1.0,319,1000,0000,00000,4244,0,0,0,D\r\n', + 'oko': '{123456789012345,090745,A,4944.302,N,02353.366,E,0.0,225,251120,7,0.27,F9,11.3,1}', + 'ivt401': '(TLN,123456789012345,250118,063827,+18.598098,+73.806518,0,79,0,1,1,5,1200,0,0.0,11.50,4.00,36,0,0,1.00,0,0,12702,202,0);', + 't57': '*T57#F1#1234567890#301117#000843#2234.1303#N#08826.1714#E#+0.242,+0.109,-0.789#0.000#6.20000#A2#4.2#', + 'm2c': '[#M2C,2020,P1.B1.H1.F1.R1,101,123456789012345,2,L,1,100,170704,074933,28.647556,77.192940,900,194,0.0,0,0,0,255,11942,0,0,0,0,0,0,0,0,30068,5051,0,0,1*8159\r\n]', + 'cautela': '20,123456789012,14,02,18,16.816667,96.166667,1325,S,*2E\r\n', + 'pt60': '@B#@|01|001|123456789012345|9425010450971470|1|45|20181127122717|32.701093|35.570938|1|@R#@', } baseUrl = 'http://localhost:8082' -- cgit v1.2.3 From a9f0507d6c08aa00afb41d9e3222cdfdafd54740 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 17 Jul 2022 09:09:50 -0700 Subject: More integration tests --- tools/test-integration.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/test-integration.py b/tools/test-integration.py index 42922147e..4a590128f 100755 --- a/tools/test-integration.py +++ b/tools/test-integration.py @@ -89,7 +89,7 @@ messages = { 'siwi' : '$SIWI,1234,1320,A,0,,1,1,0,0,876578,43,10,A,19.0123456,72.65347,45,0,055929,071107,22,5,1,0,3700,1210,0,2500,1230,321,0,1.1,4.0,1!\r\n', 'starlink' : '$SLU123456,06,622,170329035057,01,170329035057,+3158.0018,+03446.6968,004.9,007,000099,1,1,0,0,0,0,0,0,,,14.176,03.826,,1,1,1,4*B0\r\n', 'alematics' : '$T,50,592,123456789012345,20170515062915,20170515062915,25.035005,121.561555,0,31,89,3.7,5,1,0,0.000,12.752,1629,38,12752,4203,6\r\n', - 'vtfms' : '(123456789012345,00I76,00,000,,,,,A,133755,210617,10.57354,077.24912,SW,000,00598,00000,K,0017368,1,12.7,,,0.000,,,0,0,0,0,1,1,0,,)074' + 'vtfms' : '(123456789012345,00I76,00,000,,,,,A,133755,210617,10.57354,077.24912,SW,000,00598,00000,K,0017368,1,12.7,,,0.000,,,0,0,0,0,1,1,0,,)074', 'esky': 'ET;0;123456789012345;R;6+190317162511+41.32536+19.83144+0.14+0+0x0+0+18460312+0+1233+192', 'genx': '123456789012345,08/31/2017 17:24:13,45.47275,-73.65491,5,19,117,1.14,147,ON,1462,0,6,N,0,0.000,-95.0,-1.0,0,0.0000,0.0000,0.000,0,0.00,0.00,0.00,NA,U,UUU,0,-95.0,U\r\n', 'dway': 'AA55,115,1234,1,171024,195059,28.0153,-82.4761,3, 1.0,319,1000,0000,00000,4244,0,0,0,D\r\n', @@ -99,6 +99,16 @@ messages = { 'm2c': '[#M2C,2020,P1.B1.H1.F1.R1,101,123456789012345,2,L,1,100,170704,074933,28.647556,77.192940,900,194,0.0,0,0,0,255,11942,0,0,0,0,0,0,0,0,30068,5051,0,0,1*8159\r\n]', 'cautela': '20,123456789012,14,02,18,16.816667,96.166667,1325,S,*2E\r\n', 'pt60': '@B#@|01|001|123456789012345|9425010450971470|1|45|20181127122717|32.701093|35.570938|1|@R#@', + 'telemax': '%061234560128\r\nY000007C6999999067374074649003C00A7018074666F60D66818051304321900000000C5\r\n', + 'svias': '[7061,3041,57,1234567890,710,40618,141342,-93155840,-371754060,0,20469,0,16,1,0,0,11323,100,9,,32,4695]', + 'eseal': '##S,eSeal,123456,256,3.0.6,Normal,34,2017-08-31,08:14:40,15,A,25.708828N 100.372870W,10,0,Close,0.71,0:0:3:0,3.8,-73,E##\r\n', + 'avema': '1234567890,20190522093835,121.645898,25.062268,0,0,0,0,3,0.0,1,0.02,11.48,0,0,19,4,466-5,65534,56589841,0.01\r\n', + 'milesmate': 'ApiString={A:123456789012345,B:09.8,C:00.0,D:083506,E:2838.5529N,F:07717.8049E,G:000.00,H:170918,I:G,J:00004100,K:0000000A,L:1234,M:126.86}\r\n', + 'smartsole': '#GTXRP=123456789012345,8,180514200051,34.041981,-118.255806,60,1,1,7,1.80,180514200051,4.16,11$', + 'its': '$,EPB,SEM,123456789012345,NM,14072020112020,A,28.359959,N,076.927566,E,260.93,0.1,0.0,G,NA00000000,N.A0000000,*', + 'xrb28': '*SCOR,OM,123456789012345,D0,0,012102.00,A,0608.00062,S,10659.70331,E,12,0.69,151118,30.3,M,A#\r\n', + 'c2stek': 'PA$123456789012345$D#220222#135059#0#+37.98995#+23.85141#0.00#69.2#0.0#0000#000#8#00#sz-w1001#B2600$AP', + 'mictrack': 'MT;6;123456789012345;R0;10+190109091803+22.63827+114.02922+2.14+69+2+3744+113', } baseUrl = 'http://localhost:8082' -- cgit v1.2.3 From 6ea6561d4fab3a04d4fd388c68b8754488f5fe3f Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 6 Aug 2022 21:00:43 -0700 Subject: Add integration tests --- tools/test-integration.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'tools') diff --git a/tools/test-integration.py b/tools/test-integration.py index 4a590128f..454585440 100755 --- a/tools/test-integration.py +++ b/tools/test-integration.py @@ -109,6 +109,11 @@ messages = { 'xrb28': '*SCOR,OM,123456789012345,D0,0,012102.00,A,0608.00062,S,10659.70331,E,12,0.69,151118,30.3,M,A#\r\n', 'c2stek': 'PA$123456789012345$D#220222#135059#0#+37.98995#+23.85141#0.00#69.2#0.0#0000#000#8#00#sz-w1001#B2600$AP', 'mictrack': 'MT;6;123456789012345;R0;10+190109091803+22.63827+114.02922+2.14+69+2+3744+113', + 'plugin': '$$STATUS123456,20190528143943,28.254086,-25.860665,0,0,0,-1,2,78,11395,0,0,0#', + 'racedynamics': '$GPRMC,12,260819,100708,123456789012345,\r\n$GPRMC,15,04,H,#,100632,A,1255.5106,N,07738.2954,E,001,260819,0887,06,1,00011,%,0000000000000000,000,000,0,0,1,0713,0,416,0,255,000,0,000,3258,000,000,00,0000,000,00000,0,F3VF01\r\n', + 's168': 'S168#123456789012345#0f12#0077#LOCA:G;CELL:1,1cc,2,2795,1435,64;GDATA:A,12,160412154800,22.564025,113.242329,5.5,152,900;ALERT:0000;STATUS:89,98;WAY:0$', + 'dingtek': '800001011e0692001a00000000016e008027c40000112345678901234581', + 'portman': '$PTMLA,123456789012345,A,200612153351,N2543.0681W10009.2974,0,190,NA,C9830000,NA,108,8,2.66,16,GNA\r\n', } baseUrl = 'http://localhost:8082' -- cgit v1.2.3 From 18addfa5b5535dbf8d48c7bbfd01c7234e0154bf Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 16 Aug 2022 14:38:17 -0700 Subject: Change ignition test --- tools/test-generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/test-generator.py b/tools/test-generator.py index eb50d2600..d49b98744 100755 --- a/tools/test-generator.py +++ b/tools/test-generator.py @@ -74,7 +74,7 @@ while True: speed = device_speed if (index % len(points)) != 0 else 0 alarm = (index % 10) == 0 battery = random.randint(0, 100) - ignition = (index % len(points)) != 0 + ignition = (index / 10 % 2) != 0 accuracy = 100 if (index % 10) == 0 else 0 rpm = random.randint(500, 4000) fuel = random.randint(0, 80) -- cgit v1.2.3 From 0cbd1277407977690c678d5a5e92ca6353dc608a Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 2 Oct 2022 12:41:47 -0700 Subject: Add integration tests --- tools/test-integration.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'tools') diff --git a/tools/test-integration.py b/tools/test-integration.py index 454585440..34f81ee83 100755 --- a/tools/test-integration.py +++ b/tools/test-integration.py @@ -114,6 +114,11 @@ messages = { 's168': 'S168#123456789012345#0f12#0077#LOCA:G;CELL:1,1cc,2,2795,1435,64;GDATA:A,12,160412154800,22.564025,113.242329,5.5,152,900;ALERT:0000;STATUS:89,98;WAY:0$', 'dingtek': '800001011e0692001a00000000016e008027c40000112345678901234581', 'portman': '$PTMLA,123456789012345,A,200612153351,N2543.0681W10009.2974,0,190,NA,C9830000,NA,108,8,2.66,16,GNA\r\n', + 'futureway': '410000003F2000020,IMEI:123456789012345,battery level:6,network type:7,CSQ:236F42410000009BA00004GPS:V,200902093333,0.000000N,0.000000E,0.000,0.000\r\nWIFI:3,1|90-67-1C-F7-21-6C|52&2|80-89-17-C6-79-A0|54&3|40-F4-20-EF-DD-2A|58\r\nLBS:460,0,46475066,69\r\n6A42', + 'net': '@L03612345678901234512271020161807037078881037233751000000010F850036980A4000!', + 'mobilogix': '[2020-10-25 20:45:09,T9,1,V1.2.3,123456789012,59,10.50,701,-25.236860,-45.708530,0,314]', + 'swiftech': '@@123456789012345,,0,102040,1023.9670,N,07606.8160,E,2.26,151220,A,0127,1,1,03962,00000,#', + 'ennfu': 'Ennfu:123456789012345,041504.00,A,3154.86654,N,11849.08737,E,0.053,,080121,20,3.72,21.4,V0.01$', } baseUrl = 'http://localhost:8082' -- cgit v1.2.3 From 938872ff5e2fad867720ec9c971ea432ba623c2c Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 27 Nov 2022 16:17:00 -0800 Subject: Update python version --- tools/test-commands.py | 2 +- tools/test-generator.py | 2 +- tools/test-integration.py | 2 +- tools/test-map.py | 2 +- tools/test-performance.py | 2 +- tools/test-trips.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/test-commands.py b/tools/test-commands.py index 040efb177..6e310051a 100755 --- a/tools/test-commands.py +++ b/tools/test-commands.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 import socket import binascii diff --git a/tools/test-generator.py b/tools/test-generator.py index d49b98744..6e30c7fea 100755 --- a/tools/test-generator.py +++ b/tools/test-generator.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 import sys import math diff --git a/tools/test-integration.py b/tools/test-integration.py index 34f81ee83..f926a8ae9 100755 --- a/tools/test-integration.py +++ b/tools/test-integration.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 import sys import os diff --git a/tools/test-map.py b/tools/test-map.py index ab4466b09..5808c1fbb 100755 --- a/tools/test-map.py +++ b/tools/test-map.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 import urllib import urllib2 diff --git a/tools/test-performance.py b/tools/test-performance.py index ec31e9b86..a2dd6e66d 100755 --- a/tools/test-performance.py +++ b/tools/test-performance.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 import asyncio import random diff --git a/tools/test-trips.py b/tools/test-trips.py index a71357fdb..267752fbb 100755 --- a/tools/test-trips.py +++ b/tools/test-trips.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 import urllib import httplib -- cgit v1.2.3 From 6142cf557dc130828c12dbfb25ab18eda4bc0f7d Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 27 Nov 2022 16:19:49 -0800 Subject: Update python scripts --- tools/test-generator.py | 4 ++-- tools/test-integration.py | 4 ++-- tools/test-map.py | 6 +++--- tools/test-trips.py | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'tools') diff --git a/tools/test-generator.py b/tools/test-generator.py index 6e30c7fea..ed135b4aa 100755 --- a/tools/test-generator.py +++ b/tools/test-generator.py @@ -3,7 +3,7 @@ import sys import math import urllib -import httplib +import http.client as httplib import time import random @@ -51,7 +51,7 @@ def send(conn, lat, lon, altitude, course, speed, battery, alarm, ignition, accu params = params + (('fuel', fuel),) if driverUniqueId: params = params + (('driverUniqueId', driverUniqueId),) - conn.request('GET', '?' + urllib.urlencode(params)) + conn.request('GET', '?' + urllib.parse.urlencode(params)) conn.getresponse().read() def course(lat1, lon1, lat2, lon2): diff --git a/tools/test-integration.py b/tools/test-integration.py index f926a8ae9..89f1c76ed 100755 --- a/tools/test-integration.py +++ b/tools/test-integration.py @@ -140,7 +140,7 @@ def load_ports(): def login(): request = urllib2.Request(baseUrl + '/api/session') - response = urllib2.urlopen(request, urllib.urlencode(user)) + response = urllib2.urlopen(request, urllib.parse.urlencode(user)) if debug: print '\nlogin: %s\n' % repr(json.load(response)) return response.headers.get('Set-Cookie') @@ -176,7 +176,7 @@ def send_message(port, message): def get_protocols(cookie, device_id): params = { 'deviceId' : device_id, 'from' : '2000-01-01T00:00:00.000Z', 'to' : '2050-01-01T00:00:00.000Z' } - request = urllib2.Request(baseUrl + '/api/positions?' + urllib.urlencode(params)) + request = urllib2.Request(baseUrl + '/api/positions?' + urllib.parse.urlencode(params)) request.add_header('Cookie', cookie) request.add_header('Content-Type', 'application/json') request.add_header('Accept', 'application/json') diff --git a/tools/test-map.py b/tools/test-map.py index 5808c1fbb..362c95878 100755 --- a/tools/test-map.py +++ b/tools/test-map.py @@ -2,7 +2,7 @@ import urllib import urllib2 -import httplib +import http.client as httplib import time import random import json @@ -14,7 +14,7 @@ devices = 500 def login(): request = urllib2.Request(baseUrl + '/api/session') - response = urllib2.urlopen(request, urllib.urlencode(user)) + response = urllib2.urlopen(request, urllib.parse.urlencode(user)) return response.headers.get('Set-Cookie') def add_device(cookie, unique_id): @@ -29,7 +29,7 @@ def add_device(cookie, unique_id): def send_message(conn, device_id): params = (('id', device_id), ('lat', random.uniform(59, 61)), ('lon', random.uniform(29, 31))) - conn.request('GET', '?' + urllib.urlencode(params)) + conn.request('GET', '?' + urllib.parse.urlencode(params)) conn.getresponse().read() cookie = login() diff --git a/tools/test-trips.py b/tools/test-trips.py index 267752fbb..3c994fd83 100755 --- a/tools/test-trips.py +++ b/tools/test-trips.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import urllib -import httplib +import http.client as httplib import time import datetime @@ -25,7 +25,7 @@ points = [ def send(conn, time, lat, lon, speed): params = (('id', id), ('timestamp', int(time)), ('lat', lat), ('lon', lon), ('speed', speed)) - conn.request('POST', '?' + urllib.urlencode(params)) + conn.request('POST', '?' + urllib.parse.urlencode(params)) conn.getresponse().read() conn = httplib.HTTPConnection(server) -- cgit v1.2.3 From 11f90f5b779e9af3a22907766254f3400ef8bc50 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 14 Dec 2022 12:42:56 -0800 Subject: Fix recovery script --- tools/recover.py | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'tools') diff --git a/tools/recover.py b/tools/recover.py index 01e01f92e..dfa94c978 100755 --- a/tools/recover.py +++ b/tools/recover.py @@ -1,35 +1,52 @@ -#!/usr/bin/python +#!/usr/bin/env python3 import sys import re +import os +import xml.etree.ElementTree import socket import binascii +import time if len(sys.argv) < 2: sys.exit("log file is not provided") path = sys.argv[1] -p = re.compile(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} DEBUG: \[([0-9a-fA-F]{8}): (\d+) < [\d.]+] HEX: ([0-9a-fA-F]+)") +p = re.compile(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} INFO: \[([TU][0-9a-fA-F]{8}): (\S+) < [\d.]+] ([0-9a-fA-F]+)") -ports = {} +def load_ports(): + ports = {} + dir = os.path.dirname(os.path.abspath(__file__)) + root = xml.etree.ElementTree.parse(dir + '/../setup/default.xml').getroot() + for entry in root.findall('entry'): + key = entry.attrib['key'] + if key.endswith('.port'): + ports[key[:-5]] = int(entry.text) + return ports + +ports = load_ports() +protocols = {} messages = {} for line in open(path): - if "HEX:" in line: - m = p.match(line) - if m: - session = m.group(1) - port = m.group(2) - message = m.group(3) - ports[session] = port - if session not in messages: - messages[session] = [] - messages[session].append(message) - -for session in ports: - port = ports[session] + print(line) + m = p.match(line) + if m: + session = m.group(1) + protocol = m.group(2) + message = m.group(3) + protocols[session] = protocol + if session not in messages: + messages[session] = [] + messages[session].append(message) + +print('Total: %d' % len(messages)) + +for session in protocols: + port = ports[protocols[session]] s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("localhost", int(port))) for message in messages[session]: s.send(binascii.unhexlify(message)) + time.sleep(0.5) s.close() -- cgit v1.2.3 From 3b36ac38a0c4e193ea8085eb5556dffd8205bb17 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 14 Dec 2022 16:08:25 -0800 Subject: Handle motion fluctuation (fix #5000) --- schema/changelog-5.6.xml | 17 +++++++++++++++++ schema/changelog-master.xml | 1 + .../org/traccar/handler/events/MotionEventHandler.java | 2 +- src/main/java/org/traccar/model/Device.java | 13 +++++++++++++ .../java/org/traccar/reports/common/ReportUtils.java | 4 +++- .../java/org/traccar/session/state/MotionProcessor.java | 10 ++++++++-- .../java/org/traccar/session/state/MotionState.java | 13 +++++++++++++ .../traccar/handler/events/MotionEventHandlerTest.java | 7 +++---- tools/recover.py | 2 +- 9 files changed, 60 insertions(+), 9 deletions(-) create mode 100644 schema/changelog-5.6.xml (limited to 'tools') diff --git a/schema/changelog-5.6.xml b/schema/changelog-5.6.xml new file mode 100644 index 000000000..335f7b3a8 --- /dev/null +++ b/schema/changelog-5.6.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/schema/changelog-master.xml b/schema/changelog-master.xml index cc39c5c41..0835918c9 100644 --- a/schema/changelog-master.xml +++ b/schema/changelog-master.xml @@ -36,5 +36,6 @@ + diff --git a/src/main/java/org/traccar/handler/events/MotionEventHandler.java b/src/main/java/org/traccar/handler/events/MotionEventHandler.java index 1b9763c41..c406bd935 100644 --- a/src/main/java/org/traccar/handler/events/MotionEventHandler.java +++ b/src/main/java/org/traccar/handler/events/MotionEventHandler.java @@ -75,7 +75,7 @@ public class MotionEventHandler extends BaseEventHandler { state.toDevice(device); try { storage.updateObject(device, new Request( - new Columns.Include("motionState", "motionTime", "motionDistance"), + new Columns.Include("motionStreak", "motionState", "motionTime", "motionDistance"), new Condition.Equals("id", device.getId()))); } catch (StorageException e) { LOGGER.warn("Update device motion error", e); diff --git a/src/main/java/org/traccar/model/Device.java b/src/main/java/org/traccar/model/Device.java index 7728172cb..b8c87921d 100644 --- a/src/main/java/org/traccar/model/Device.java +++ b/src/main/java/org/traccar/model/Device.java @@ -162,6 +162,19 @@ public class Device extends GroupedModel implements Disableable { this.expirationTime = expirationTime; } + private boolean motionStreak; + + @QueryIgnore + @JsonIgnore + public boolean getMotionStreak() { + return motionStreak; + } + + @JsonIgnore + public void setMotionStreak(boolean motionStreak) { + this.motionStreak = motionStreak; + } + private boolean motionState; @QueryIgnore diff --git a/src/main/java/org/traccar/reports/common/ReportUtils.java b/src/main/java/org/traccar/reports/common/ReportUtils.java index 120dadcf5..a7c420095 100644 --- a/src/main/java/org/traccar/reports/common/ReportUtils.java +++ b/src/main/java/org/traccar/reports/common/ReportUtils.java @@ -354,7 +354,9 @@ public class ReportUtils { boolean trips = reportClass.equals(TripReportItem.class); MotionState motionState = new MotionState(); - motionState.setMotionState(isMoving(positions, 0, tripsConfig)); + boolean initialValue = isMoving(positions, 0, tripsConfig); + motionState.setMotionStreak(initialValue); + motionState.setMotionState(initialValue); boolean detected = trips == motionState.getMotionState(); int startEventIndex = detected ? 0 : -1; diff --git a/src/main/java/org/traccar/session/state/MotionProcessor.java b/src/main/java/org/traccar/session/state/MotionProcessor.java index b9d706492..a1737a739 100644 --- a/src/main/java/org/traccar/session/state/MotionProcessor.java +++ b/src/main/java/org/traccar/session/state/MotionProcessor.java @@ -59,6 +59,7 @@ public final class MotionProcessor { String eventType = newState ? Event.TYPE_DEVICE_MOVING : Event.TYPE_DEVICE_STOPPED; Event event = new Event(eventType, position); + state.setMotionStreak(newState); state.setMotionTime(null); state.setMotionDistance(0); state.setEvent(event); @@ -67,8 +68,13 @@ public final class MotionProcessor { } } else { state.setMotionState(newState); - state.setMotionTime(position.getFixTime()); - state.setMotionDistance(position.getDouble(Position.KEY_TOTAL_DISTANCE)); + if (state.getMotionStreak() == newState) { + state.setMotionTime(null); + state.setMotionDistance(0); + } else { + state.setMotionTime(position.getFixTime()); + state.setMotionDistance(position.getDouble(Position.KEY_TOTAL_DISTANCE)); + } } } diff --git a/src/main/java/org/traccar/session/state/MotionState.java b/src/main/java/org/traccar/session/state/MotionState.java index e3ce58ab2..6c917ad16 100644 --- a/src/main/java/org/traccar/session/state/MotionState.java +++ b/src/main/java/org/traccar/session/state/MotionState.java @@ -24,6 +24,7 @@ public class MotionState { public static MotionState fromDevice(Device device) { MotionState state = new MotionState(); + state.motionStreak = device.getMotionStreak(); state.motionState = device.getMotionState(); state.motionTime = device.getMotionTime(); state.motionDistance = device.getMotionDistance(); @@ -31,6 +32,7 @@ public class MotionState { } public void toDevice(Device device) { + device.setMotionStreak(motionStreak); device.setMotionState(motionState); device.setMotionTime(motionTime); device.setMotionDistance(motionDistance); @@ -42,6 +44,17 @@ public class MotionState { return changed; } + private boolean motionStreak; + + public boolean getMotionStreak() { + return motionStreak; + } + + public void setMotionStreak(boolean motionStreak) { + this.motionStreak = motionStreak; + changed = true; + } + private boolean motionState; public boolean getMotionState() { diff --git a/src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java b/src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java index 25c766b51..b77676dc8 100644 --- a/src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java +++ b/src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java @@ -1,6 +1,5 @@ package org.traccar.handler.events; -import org.junit.Ignore; import org.junit.Test; import org.traccar.BaseTest; import org.traccar.model.Event; @@ -62,7 +61,6 @@ public class MotionEventHandlerTest extends BaseTest { verifyState(state, false, 0); } - @Ignore @Test public void testMotionFluctuation() throws ParseException { TripsConfig tripsConfig = new TripsConfig(500, 300000, 300000, 0, false, false, 0.01); @@ -87,11 +85,11 @@ public class MotionEventHandlerTest extends BaseTest { MotionProcessor.updateState(state, position("2017-01-01 00:04:00", true, 1000, null), true, tripsConfig); assertNull(state.getEvent()); - verifyState(state, true, 1000); + verifyState(state, true, 0); MotionProcessor.updateState(state, position("2017-01-01 00:06:00", true, 2000, null), true, tripsConfig); assertNull(state.getEvent()); - verifyState(state, true, 2000); + verifyState(state, true, 0); } @Test @@ -99,6 +97,7 @@ public class MotionEventHandlerTest extends BaseTest { TripsConfig tripsConfig = new TripsConfig(500, 300000, 300000, 0, true, false, 0.01); MotionState state = new MotionState(); + state.setMotionStreak(true); state.setMotionState(true); MotionProcessor.updateState(state, position("2017-01-01 00:00:00", false, 100, true), false, tripsConfig); diff --git a/tools/recover.py b/tools/recover.py index dfa94c978..32e3f8721 100755 --- a/tools/recover.py +++ b/tools/recover.py @@ -48,5 +48,5 @@ for session in protocols: s.connect(("localhost", int(port))) for message in messages[session]: s.send(binascii.unhexlify(message)) - time.sleep(0.5) + time.sleep(0.1) s.close() -- cgit v1.2.3 From 42f269d5f9e0829c7dbfa22ccb6b41415e6e4415 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 1 Jan 2023 11:10:35 -0800 Subject: Rename config script --- tools/config-doc.py | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/gen_config_doc.py | 102 ------------------------------------------------ 2 files changed, 102 insertions(+), 102 deletions(-) create mode 100755 tools/config-doc.py delete mode 100644 tools/gen_config_doc.py (limited to 'tools') diff --git a/tools/config-doc.py b/tools/config-doc.py new file mode 100755 index 000000000..98266386e --- /dev/null +++ b/tools/config-doc.py @@ -0,0 +1,102 @@ +#!/usr/bin/python + +import re +import os +import argparse + +_KEYS_FILE = os.path.join( + os.path.dirname(__file__), "../src/main/java/org/traccar/config/Keys.java" +) + + +def get_config_keys(): + """Parses Keys.java to extract keys to be used in configuration files + + Args: None + + Returns: + list: A list of dict containing the following keys - + 'key': A dot separated name of the config key + 'description': A list of str + """ + desc_re = re.compile(r"(/\*\*\n|\s+\*/|\s+\*)") + key_match_re = re.compile(r"\(\n(.+)\);", re.DOTALL) + key_split_re = re.compile(r",\s+", re.DOTALL) + keys = [] + + with open(_KEYS_FILE, "r") as f: + config = re.findall( + r"(/\*\*.*?\*/)\n\s+(public static final Config.*?;)", f.read(), re.DOTALL + ) + for i in config: + try: + key_match = key_match_re.search(i[1]) + if key_match: + terms = [x.strip() for x in key_split_re.split(key_match.group(1))] + key = terms[0].replace('"', "") + description = [ + x.strip().replace("\n", "") + for x in desc_re.sub("\n", i[0]).strip().split("\n\n") + ] + if len(terms) == 3: + description.append(f"Default: {terms[2]}") + keys.append( + { + "key": key, + "description": description, + } + ) + except IndexError: + # will continue if key_match.group(1) or terms[0] does not exist + # for some reason + pass + + return keys + + +def get_html(): + return ("\n").join( + [ + f"""
+
+
+ {x["key"]} config +
+

+ {"
".join(x["description"])} +

+
+
""" + for x in get_config_keys() + ] + ) + + +def get_pug(): + return ("\n").join( + [ + f""" div(class='card mt-3') + div(class='card-body') + h5(class='card-title') {x["key"]} #[span(class='badge badge-dark') config] + p(class='card-text') {"#[br] ".join(x["description"])}""" + for x in get_config_keys() + ] + ) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Parses Keys.java to extract keys to be used in configuration files" + ) + parser.add_argument( + "--format", choices=["pug", "html"], default="pug", help="default: 'pug'" + ) + args = parser.parse_args() + + def get_output(): + if args.format == 'html': + return get_html() + + return get_pug() + + print(get_output()) \ No newline at end of file diff --git a/tools/gen_config_doc.py b/tools/gen_config_doc.py deleted file mode 100644 index 98266386e..000000000 --- a/tools/gen_config_doc.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/python - -import re -import os -import argparse - -_KEYS_FILE = os.path.join( - os.path.dirname(__file__), "../src/main/java/org/traccar/config/Keys.java" -) - - -def get_config_keys(): - """Parses Keys.java to extract keys to be used in configuration files - - Args: None - - Returns: - list: A list of dict containing the following keys - - 'key': A dot separated name of the config key - 'description': A list of str - """ - desc_re = re.compile(r"(/\*\*\n|\s+\*/|\s+\*)") - key_match_re = re.compile(r"\(\n(.+)\);", re.DOTALL) - key_split_re = re.compile(r",\s+", re.DOTALL) - keys = [] - - with open(_KEYS_FILE, "r") as f: - config = re.findall( - r"(/\*\*.*?\*/)\n\s+(public static final Config.*?;)", f.read(), re.DOTALL - ) - for i in config: - try: - key_match = key_match_re.search(i[1]) - if key_match: - terms = [x.strip() for x in key_split_re.split(key_match.group(1))] - key = terms[0].replace('"', "") - description = [ - x.strip().replace("\n", "") - for x in desc_re.sub("\n", i[0]).strip().split("\n\n") - ] - if len(terms) == 3: - description.append(f"Default: {terms[2]}") - keys.append( - { - "key": key, - "description": description, - } - ) - except IndexError: - # will continue if key_match.group(1) or terms[0] does not exist - # for some reason - pass - - return keys - - -def get_html(): - return ("\n").join( - [ - f"""
-
-
- {x["key"]} config -
-

- {"
".join(x["description"])} -

-
-
""" - for x in get_config_keys() - ] - ) - - -def get_pug(): - return ("\n").join( - [ - f""" div(class='card mt-3') - div(class='card-body') - h5(class='card-title') {x["key"]} #[span(class='badge badge-dark') config] - p(class='card-text') {"#[br] ".join(x["description"])}""" - for x in get_config_keys() - ] - ) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - description="Parses Keys.java to extract keys to be used in configuration files" - ) - parser.add_argument( - "--format", choices=["pug", "html"], default="pug", help="default: 'pug'" - ) - args = parser.parse_args() - - def get_output(): - if args.format == 'html': - return get_html() - - return get_pug() - - print(get_output()) \ No newline at end of file -- cgit v1.2.3 From aa6db4e57ceb30377678c5c563c4992161de0ffe Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 1 Jan 2023 11:42:08 -0800 Subject: Update config script --- tools/config-doc.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/config-doc.py b/tools/config-doc.py index 98266386e..c55b2b5ef 100755 --- a/tools/config-doc.py +++ b/tools/config-doc.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 import re import os @@ -22,6 +22,7 @@ def get_config_keys(): desc_re = re.compile(r"(/\*\*\n|\s+\*/|\s+\*)") key_match_re = re.compile(r"\(\n(.+)\);", re.DOTALL) key_split_re = re.compile(r",\s+", re.DOTALL) + types_match_re = re.compile(r"List\.of\(([^)]+)\)", re.DOTALL) keys = [] with open(_KEYS_FILE, "r") as f: @@ -34,16 +35,18 @@ def get_config_keys(): if key_match: terms = [x.strip() for x in key_split_re.split(key_match.group(1))] key = terms[0].replace('"', "") + key = "[protocol]" + key if key.startswith('.') else key description = [ x.strip().replace("\n", "") for x in desc_re.sub("\n", i[0]).strip().split("\n\n") ] - if len(terms) == 3: - description.append(f"Default: {terms[2]}") + types_match = types_match_re.search(i[1]) + types = map(lambda x: x[8:].lower(), types_match[1].split(", ")) keys.append( { "key": key, "description": description, + "types": types, } ) except IndexError: @@ -60,7 +63,7 @@ def get_html(): f"""
- {x["key"]} config + {x["key"]}

{"
".join(x["description"])} @@ -77,7 +80,7 @@ def get_pug(): [ f""" div(class='card mt-3') div(class='card-body') - h5(class='card-title') {x["key"]} #[span(class='badge badge-dark') config] + h5(class='card-title') {x["key"]} {" ".join(map("#[span(class='badge badge-dark') {:}]".format, x["types"]))} p(class='card-text') {"#[br] ".join(x["description"])}""" for x in get_config_keys() ] @@ -99,4 +102,4 @@ if __name__ == "__main__": return get_pug() - print(get_output()) \ No newline at end of file + print(get_output()) -- cgit v1.2.3 From 38221e1a4041937f437d5f93edfdf2973c1f70b2 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 4 Feb 2023 16:23:31 -0800 Subject: Update integration tests --- tools/test-integration.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/test-integration.py b/tools/test-integration.py index 89f1c76ed..9aad642ae 100755 --- a/tools/test-integration.py +++ b/tools/test-integration.py @@ -4,7 +4,7 @@ import sys import os import xml.etree.ElementTree import urllib -import urllib2 +import urllib.request as urllib2 import json import socket import time @@ -18,10 +18,9 @@ messages = { 't55' : '$PGID,123456789012345*0F\r\n$GPRMC,120500.000,A,6000.0000,N,13000.0000,E,0.00,0.00,010112,,*33\r\n', 'xexun' : '111111120009,+436763737552,GPRMC,120600.000,A,6000.0000,N,13000.0000,E,0.00,0.00,010112,,,A*68,F,, imei:123456789012345,04,481.2,F:4.15V,0,139,2689,232,03,2725,0576\n', 'totem' : '$$B3123456789012345|AA$GPRMC,120700.000,A,6000.0000,N,13000.0000,E,0.00,,010112,,,A*74|01.8|01.0|01.5|000000000000|20120403234603|14251914|00000000|0012D888|0000|0.0000|3674|940B\r\n', - 'meiligao' : '$$\x00\x60\x12\x34\x56\xFF\xFF\xFF\xFF\x99\x55120900.000,A,6000.0000,N,13000.0000,E,0.00,,010112,,*1C|11.5|194|0000|0000,0000\x69\x62\x0D\x0A', 'suntech' : 'SA200STT;123456;042;20120101;12:11:00;16d41;-15.618767;-056.083214;000.011;000.00;11;1;41557;12.21;000000;1;3205\r', 'h02' : '*HQ,123456789012345,V1,121300,A,6000.0000,N,13000.0000,E,0.00,0.00,010112,ffffffff,000000,000000,000000,000000#', - 'jt600' : '$\x00\x00\x12\x34\x56\x11\x00\x1B\x01\x01\x12\x12\x14\x00\x60\x00\x00\x00\x13\x00\x00\x00\x0F\x00\x00\x07\x50\x00\x00\x00\x2B\x91\x04\x4D\x1F\xA1', + 'jt600' : '(1234567890,P45,290322,132412,25.28217,S,57.54683,W,A,0,0,5,0,0000000000,0,0,9,0)', 'v680' : '#123456789012345#1000#0#1000#AUT#1#66830FFB#13000.0000,E,6000.0000,N,001.41,259#010112#121600##', 'pt502' : '$POS,123456,121700.000,A,6000.0000,N,13000.0000,E,0.0,0.0,010112,,,A/00000,00000/0/23895000//\r\n', 'tr20' : '%%123456789012345,A,120101121800,N6000.0000E13000.0000,0,000,0,01034802,150,[Message]\r\n', @@ -119,6 +118,9 @@ messages = { 'mobilogix': '[2020-10-25 20:45:09,T9,1,V1.2.3,123456789012,59,10.50,701,-25.236860,-45.708530,0,314]', 'swiftech': '@@123456789012345,,0,102040,1023.9670,N,07606.8160,E,2.26,151220,A,0127,1,1,03962,00000,#', 'ennfu': 'Ennfu:123456789012345,041504.00,A,3154.86654,N,11849.08737,E,0.053,,080121,20,3.72,21.4,V0.01$', + 'startek': '&&o125,123456789012345,000,0,,210702235150,A,27.263505,153.037061,11,1.2,0,0,31,5125,505|1|7032|8C89802,20,0000002D,00,00,01E2|019DF0\r\n', + 'hoopo': '{ "deviceId": "123456789012345", "assetName": "123456789012345", "assetType": "test", "eventData": { "latitude": 31.97498, "longitude": 34.80802, "locationName": "", "accuracyLevel": "High", "eventType": "Arrival", "batteryLevel": 100, "receiveTime": "2021-09-20T18:52:32Z" }, "eventTime": "2021-09-20T08:52:02Z", "serverReportTime": "0001-01-01T00:00:00Z" }', + 'techtocruz': '$$A120,123456789012345,211005105836,A,FLEX,KCB 947C,000.0,0,-1.38047,S,36.93951,E,1648.4,243.140,21,28,12.1,3.7,0,1,0,0,0,*F6', } baseUrl = 'http://localhost:8082' @@ -135,14 +137,14 @@ def load_ports(): if key.endswith('.port'): ports[key[:-5]] = int(entry.text) if debug: - print '\nports: %s\n' % repr(ports) + print('\nports: {ports!r}\n') return ports def login(): request = urllib2.Request(baseUrl + '/api/session') - response = urllib2.urlopen(request, urllib.parse.urlencode(user)) + response = urllib2.urlopen(request, urllib.parse.urlencode(user).encode()) if debug: - print '\nlogin: %s\n' % repr(json.load(response)) + print(f'\nlogin: {json.load(response)!r}\n') return response.headers.get('Set-Cookie') def remove_devices(cookie): @@ -151,7 +153,7 @@ def remove_devices(cookie): response = urllib2.urlopen(request) data = json.load(response) if debug: - print '\ndevices: %s\n' % repr(data) + print(f'\ndevices: {data!r}\n') for device in data: request = urllib2.Request(baseUrl + '/api/devices/' + str(device['id'])) request.add_header('Cookie', cookie) @@ -163,14 +165,14 @@ def add_device(cookie, unique_id): request.add_header('Cookie', cookie) request.add_header('Content-Type', 'application/json') device = { 'name' : unique_id, 'uniqueId' : unique_id } - response = urllib2.urlopen(request, json.dumps(device)) + response = urllib2.urlopen(request, json.dumps(device).encode()) data = json.load(response) return data['id'] def send_message(port, message): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', port)) - s.send(message) + s.send(message.encode('ascii')) time.sleep(0.5) s.close() @@ -203,9 +205,9 @@ if __name__ == "__main__": all = set(ports.keys()) protocols = set(messages.keys()) - print 'Total: %d' % len(all) - print 'Missing: %d' % len(all - protocols) - print 'Covered: %d' % len(protocols) + print(f'Total: {len(all)}') + print(f'Missing: {len(all - protocols)}') + print(f'Covered: {len(protocols)}') for protocol in messages: send_message(ports[protocol], messages[protocol]) @@ -213,8 +215,8 @@ if __name__ == "__main__": for device in devices: protocols -= set(get_protocols(cookie, devices[device])) - print 'Success: %d' % (len(messages) - len(protocols)) - print 'Failed: %d' % len(protocols) + print(f'Success: {len(messages) - len(protocols)}') + print(f'Failed:{len(protocols)}') if protocols: - print '\nFailed: %s' % repr(list(protocols)) + print(f'\nFailed: {list(protocols)!r}') -- cgit v1.2.3 From 7c67b6f9b46a350ae111eff2caea5981dc0e1bff Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 26 Mar 2023 07:07:46 -0700 Subject: Fix map testing script --- tools/test-map.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/test-map.py b/tools/test-map.py index 362c95878..664917eff 100755 --- a/tools/test-map.py +++ b/tools/test-map.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import urllib -import urllib2 +import urllib.request as urllib2 import http.client as httplib import time import random @@ -14,7 +14,7 @@ devices = 500 def login(): request = urllib2.Request(baseUrl + '/api/session') - response = urllib2.urlopen(request, urllib.parse.urlencode(user)) + response = urllib2.urlopen(request, urllib.parse.urlencode(user).encode()) return response.headers.get('Set-Cookie') def add_device(cookie, unique_id): @@ -23,7 +23,7 @@ def add_device(cookie, unique_id): request.add_header('Content-Type', 'application/json') device = { 'name' : unique_id, 'uniqueId' : unique_id } try: - response = urllib2.urlopen(request, json.dumps(device)) + response = urllib2.urlopen(request, json.dumps(device).encode()) except urllib2.HTTPError: pass -- cgit v1.2.3 From 514605fc0070c7365e525141b6bdd64f5dffadc7 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 16 Apr 2023 10:17:09 -0700 Subject: Add integration tests --- tools/test-integration.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'tools') diff --git a/tools/test-integration.py b/tools/test-integration.py index 9aad642ae..84d2fa2e3 100755 --- a/tools/test-integration.py +++ b/tools/test-integration.py @@ -121,6 +121,11 @@ messages = { 'startek': '&&o125,123456789012345,000,0,,210702235150,A,27.263505,153.037061,11,1.2,0,0,31,5125,505|1|7032|8C89802,20,0000002D,00,00,01E2|019DF0\r\n', 'hoopo': '{ "deviceId": "123456789012345", "assetName": "123456789012345", "assetType": "test", "eventData": { "latitude": 31.97498, "longitude": 34.80802, "locationName": "", "accuracyLevel": "High", "eventType": "Arrival", "batteryLevel": 100, "receiveTime": "2021-09-20T18:52:32Z" }, "eventTime": "2021-09-20T08:52:02Z", "serverReportTime": "0001-01-01T00:00:00Z" }', 'techtocruz': '$$A120,123456789012345,211005105836,A,FLEX,KCB 947C,000.0,0,-1.38047,S,36.93951,E,1648.4,243.140,21,28,12.1,3.7,0,1,0,0,0,*F6', + 'flexapi': '${"topic":"v1/123456789012345/motion/info","payload":{"motion.ts":1641885877,"motion.ax":0.006344,"motion.ay":0.289384,"motion.az":-0.939156,"motion.gx":0.420000,"motion.gy":0.420000,"motion.gz":-0.280000}}xx\r\n', + 'jido': '*123456789012345,03,130517,160435,1820.5845,N,07833.2478,E,1,58#', + 'armoli': '[M123456789012345210122125205N38.735641E035.4727751E003340000000C00000E9E07FF:106AG505283H60E];', + 'teratrack': '{"MDeviceID":"022043756090","DiviceType":"1","DataType":"1","DataLength":"69","DateTime":"2022-03-09 10:56:01","Latitude":"-6.846451","Longitude":"39.316324","LongitudeState":"1","LatitudeState":"0","Speed":"90","Mileage":"0","FenceAlarm":"0","AreaAlarmID":"0","LockCutOff":"0","SealTampered":"0","MessageAck":"1","LockRope":"1","LockStatus":"1","LockOpen":"0","PasswordError":"0","CardNo":"60000644","IllegalCard":"0","LowPower":"0","UnCoverBack":"0","CoverStatus":"1","LockStuck":"0","Power":"79","GSM":"16","IMEI":"123456789012345","Index":"20","Slave":[]}', + 'envotech': '$80SLM,02,F,123456,130410155921,431750216,000040,0000,,00000000,\'13041015592110476673N10111459E001281*2A#', } baseUrl = 'http://localhost:8082' -- cgit v1.2.3 From ab801e856521356ff7a33250e1abdb8857ef84b3 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 19 Apr 2023 06:29:50 -0700 Subject: Fix group commands --- src/main/java/org/traccar/api/resource/CommandResource.java | 6 ++++-- tools/test-commands.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/src/main/java/org/traccar/api/resource/CommandResource.java b/src/main/java/org/traccar/api/resource/CommandResource.java index 7ba1ee2b4..b69d4d9ac 100644 --- a/src/main/java/org/traccar/api/resource/CommandResource.java +++ b/src/main/java/org/traccar/api/resource/CommandResource.java @@ -28,6 +28,7 @@ import org.traccar.model.Command; import org.traccar.model.Device; import org.traccar.model.Group; import org.traccar.model.Position; +import org.traccar.model.QueuedCommand; import org.traccar.model.Typed; import org.traccar.model.User; import org.traccar.model.UserRestrictions; @@ -121,8 +122,9 @@ public class CommandResource extends ExtendedObjectResource { permissionsService.checkPermission(Group.class, getUserId(), groupId); var devices = DeviceUtil.getAccessibleDevices(storage, getUserId(), List.of(), List.of(groupId)); for (Device device : devices) { - entity.setDeviceId(device.getId()); - result = result && commandsManager.sendCommand(entity); + Command command = QueuedCommand.fromCommand(entity).toCommand(); + command.setDeviceId(device.getId()); + result = result && commandsManager.sendCommand(command); } } else { permissionsService.checkPermission(Device.class, getUserId(), entity.getDeviceId()); diff --git a/tools/test-commands.py b/tools/test-commands.py index 6e310051a..7efd963b4 100755 --- a/tools/test-commands.py +++ b/tools/test-commands.py @@ -6,9 +6,9 @@ import binascii s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("localhost", 5001)) #s.send(binascii.unhexlify('68680f0504035889905831401700df1a00000d0a')) -s.send("imei:123456789012345,tracker,151030080103,,F,000101.000,A,5443.3834,N,02512.9071,E,0.00,0;") +s.send(b"imei:123456789012345,tracker,151030080103,,F,000101.000,A,5443.3834,N,02512.9071,E,0.00,0;") while True: - print s.recv(1024) + print(s.recv(1024)) s.close() -- cgit v1.2.3 From 41d7a5ad4c32d3911d6096802f0339ebe4bc0f39 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 30 May 2023 14:01:25 -0700 Subject: Add integration test --- tools/test-integration.py | 1 + 1 file changed, 1 insertion(+) (limited to 'tools') diff --git a/tools/test-integration.py b/tools/test-integration.py index 84d2fa2e3..204fecb70 100755 --- a/tools/test-integration.py +++ b/tools/test-integration.py @@ -126,6 +126,7 @@ messages = { 'armoli': '[M123456789012345210122125205N38.735641E035.4727751E003340000000C00000E9E07FF:106AG505283H60E];', 'teratrack': '{"MDeviceID":"022043756090","DiviceType":"1","DataType":"1","DataLength":"69","DateTime":"2022-03-09 10:56:01","Latitude":"-6.846451","Longitude":"39.316324","LongitudeState":"1","LatitudeState":"0","Speed":"90","Mileage":"0","FenceAlarm":"0","AreaAlarmID":"0","LockCutOff":"0","SealTampered":"0","MessageAck":"1","LockRope":"1","LockStatus":"1","LockOpen":"0","PasswordError":"0","CardNo":"60000644","IllegalCard":"0","LowPower":"0","UnCoverBack":"0","CoverStatus":"1","LockStuck":"0","Power":"79","GSM":"16","IMEI":"123456789012345","Index":"20","Slave":[]}', 'envotech': '$80SLM,02,F,123456,130410155921,431750216,000040,0000,,00000000,\'13041015592110476673N10111459E001281*2A#', + 'bstpl': 'BSTPL$1,123456789012345,V,200722,045113,00.000000,0,00.00000,0,0,0,000,00,0,17,1,1,0,0,00.01,0,04.19,15B_190821,8991000907387031196F,12.27#', } baseUrl = 'http://localhost:8082' -- cgit v1.2.3