├── .gitignore ├── README.md ├── pom.xml ├── src ├── test │ └── java │ │ └── net │ │ └── gcdc │ │ └── camdenm │ │ ├── UperEncoderDecodeTest.java │ │ ├── ICLCMTest.java │ │ └── CoopItsTest.java └── main │ └── java │ └── net │ └── gcdc │ └── camdenm │ └── Iclcm.java └── LICENSE.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .settings 3 | .project 4 | .classpath 5 | 6 | # IDEA 7 | .idea/ 8 | *.iml 9 | 10 | # Build tool 11 | target 12 | project/target 13 | project/project/target 14 | bin/ 15 | 16 | # OS generated files 17 | .DS_Store 18 | .DS_Store? 19 | ._* 20 | .Spotlight-V100 21 | .Trashes 22 | ehthumbs.db 23 | Thumbs.db 24 | 25 | doc/img/stack.aux 26 | 27 | doc/img/stack.log 28 | 29 | doc/img/stack.pdf 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CAM and DENM 2 | 3 | Basic Java classes to represent Cooperative Awareness Message (CAM, [ETSI EN 302 637-2](http://webapp.etsi.org/workprogram/Report_WorkItem.asp?WKI_ID=37126)) and Decentralized Environment Notification Message (DENM, [ETSI EN 302 637-3](http://webapp.etsi.org/workprogram/Report_WorkItem.asp?WKI_ID=37127)). CAM and DENM are built on top of Common Data Dictionary (CDD, [ETSI TS 102 894-2](http://webapp.etsi.org/workprogram/Report_WorkItem.asp?WKI_ID=43353)). Classes are annoted with [asn1-datatypes](https://github.com/alexvoronov/gcdc-asn1), so that [asn1-uper](https://github.com/alexvoronov/gcdc-asn1) can pack the objects. 4 | 5 | ### Status 6 | 7 | CAM and DENM are complete (except for the getter methods). Usage examples for CAM and DENM are in [uppertester](https://github.com/alexvoronov/gn-uppertester). 8 | 9 | 10 | ### Acknowledgements 11 | This implementation was partly developed within [i-GAME](http://gcdc.net/i-game) project that has received funding from the European Union's Seventh Framework Programme for research, technological development and demonstration under grant agreement no [612035](http://cordis.europa.eu/project/rcn/110506_en.html). 12 | 13 | 14 | ### License 15 | 16 | This code is released under Apache 2.0 license. 17 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | net.gcdc 5 | camdenm 6 | 1.1.0 7 | CAM and DENM message spec 8 | jar 9 | 2015 10 | 11 | 12 | 1.7 13 | 1.7 14 | UTF-8 15 | 16 | 17 | 18 | 19 | Apache License, Version 2.0 20 | http://www.apache.org/licenses/LICENSE-2.0.txt 21 | repo 22 | A business-friendly OSS license 23 | 24 | 25 | 26 | 27 | 28 | junit 29 | junit 30 | 4.13.1 31 | test 32 | 33 | 34 | net.gcdc 35 | asn1-datatypes 36 | 1.1.0 37 | 38 | 39 | net.gcdc 40 | asn1-uper 41 | 1.1.0 42 | test 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/test/java/net/gcdc/camdenm/UperEncoderDecodeTest.java: -------------------------------------------------------------------------------- 1 | package net.gcdc.camdenm; 2 | 3 | import static org.junit.Assert.assertArrayEquals; 4 | import static org.junit.Assert.assertEquals; 5 | import net.gcdc.asn1.uper.UperEncoder; 6 | import net.gcdc.camdenm.CoopIts.AccelerationControl; 7 | import net.gcdc.camdenm.CoopIts.Altitude; 8 | import net.gcdc.camdenm.CoopIts.AltitudeConfidence; 9 | import net.gcdc.camdenm.CoopIts.AltitudeValue; 10 | import net.gcdc.camdenm.CoopIts.BasicContainer; 11 | import net.gcdc.camdenm.CoopIts.BasicVehicleContainerHighFrequency; 12 | import net.gcdc.camdenm.CoopIts.Cam; 13 | import net.gcdc.camdenm.CoopIts.CamParameters; 14 | import net.gcdc.camdenm.CoopIts.CoopAwareness; 15 | import net.gcdc.camdenm.CoopIts.DangerousGoodsBasic; 16 | import net.gcdc.camdenm.CoopIts.DangerousGoodsExtended; 17 | import net.gcdc.camdenm.CoopIts.DrivingLaneStatus; 18 | import net.gcdc.camdenm.CoopIts.HeadingValue; 19 | import net.gcdc.camdenm.CoopIts.HighFrequencyContainer; 20 | //import static org.junit.Assert.fail; 21 | import net.gcdc.camdenm.CoopIts.ItsPduHeader; 22 | import net.gcdc.camdenm.CoopIts.ItsPduHeader.MessageId; 23 | import net.gcdc.camdenm.CoopIts.ItsPduHeader.ProtocolVersion; 24 | import net.gcdc.camdenm.CoopIts.Latitude; 25 | import net.gcdc.camdenm.CoopIts.Longitude; 26 | import net.gcdc.camdenm.CoopIts.PosConfidenceEllipse; 27 | import net.gcdc.camdenm.CoopIts.PosPillar; 28 | import net.gcdc.camdenm.CoopIts.PositionOfPillars; 29 | import net.gcdc.camdenm.CoopIts.PtActivationData; 30 | import net.gcdc.camdenm.CoopIts.RSUContainerHighFrequency; 31 | import net.gcdc.camdenm.CoopIts.ReferencePosition; 32 | import net.gcdc.camdenm.CoopIts.SemiAxisLength; 33 | import net.gcdc.camdenm.CoopIts.StationID; 34 | import net.gcdc.camdenm.CoopIts.StationType; 35 | import net.gcdc.camdenm.CoopIts.VDS; 36 | import net.gcdc.camdenm.CoopIts.VehicleIdentification; 37 | import net.gcdc.camdenm.CoopIts.WMInumber; 38 | 39 | import org.junit.Test; 40 | import org.slf4j.Logger; 41 | import org.slf4j.LoggerFactory; 42 | 43 | public class UperEncoderDecodeTest { 44 | private final static Logger logger = LoggerFactory.getLogger(UperEncoderDecodeTest.class); 45 | 46 | @Test public void decodeTest1() throws IllegalArgumentException, IllegalAccessException, InstantiationException { 47 | Object pdu = new ItsPduHeader(new ProtocolVersion(13), new MessageId(15), new StationID(17)); 48 | byte[] encoded = UperEncoder.encode(pdu); 49 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 50 | assertEquals("0D0F00000011", 51 | UperEncoder.hexStringFromBytes(encoded)); 52 | 53 | ItsPduHeader decoded = UperEncoder.decode(encoded, ItsPduHeader.class); 54 | logger.debug("decoded: {}", decoded); 55 | byte[] reencoded = UperEncoder.encode(decoded); 56 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(reencoded)); 57 | assertEquals("0D0F00000011", 58 | UperEncoder.hexStringFromBytes(reencoded)); 59 | 60 | } 61 | 62 | @Test public void decodeChoice1() { 63 | Object pdu = 64 | new CoopIts.Cam( 65 | new ItsPduHeader(new MessageId(MessageId.cam)), 66 | new CoopAwareness( 67 | new CoopIts.GenerationDeltaTime(100), 68 | new CamParameters( 69 | new BasicContainer( 70 | new StationType(CoopIts.StationType.tram), 71 | new ReferencePosition( 72 | new Latitude(57), 73 | new Longitude(13), 74 | new PosConfidenceEllipse( 75 | new SemiAxisLength(42), 76 | new SemiAxisLength(42), 77 | new HeadingValue(42)), 78 | new Altitude( 79 | new AltitudeValue(42), 80 | AltitudeConfidence.unavailable))), 81 | new HighFrequencyContainer( 82 | BasicVehicleContainerHighFrequency.builder() 83 | .accelerationControl(AccelerationControl.builder() 84 | .accEngaged(true) 85 | .gasPedalEngaged(true) 86 | .create()) 87 | .create())))); 88 | byte[] encoded = UperEncoder.encode(pdu); 89 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 90 | String expectedHex = "010200000000006400B6B49D272D693A41A05405405430D95E40E11FDFFFFEBFE9ED0737530F5FFFB090"; 91 | assertEquals("encoded hex not equal", expectedHex, 92 | UperEncoder.hexStringFromBytes(encoded)); 93 | 94 | Cam decoded = UperEncoder.decode(encoded, Cam.class); 95 | logger.debug("decoded: {}", decoded); 96 | byte[] reencoded = UperEncoder.encode(decoded); 97 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(reencoded)); 98 | assertEquals("reencoded hex not equal", expectedHex, 99 | UperEncoder.hexStringFromBytes(reencoded)); 100 | 101 | } 102 | 103 | @Test public void decodeChoice2() { 104 | Object pdu = 105 | new CoopIts.Cam( 106 | new ItsPduHeader(new MessageId(MessageId.cam)), 107 | new CoopAwareness( 108 | new CoopIts.GenerationDeltaTime(100), 109 | new CamParameters( 110 | new BasicContainer( 111 | new StationType(CoopIts.StationType.tram), 112 | new ReferencePosition( 113 | new Latitude(57), 114 | new Longitude(13), 115 | new PosConfidenceEllipse( 116 | new SemiAxisLength(42), 117 | new SemiAxisLength(42), 118 | new HeadingValue(42)), 119 | new Altitude( 120 | new AltitudeValue(42), 121 | AltitudeConfidence.unavailable))), 122 | new HighFrequencyContainer( 123 | new RSUContainerHighFrequency(null) 124 | )))); 125 | byte[] encoded = UperEncoder.encode(pdu); 126 | logger.debug("encodedChoice2 data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 127 | String expectedHex = "010200000000006400B6B49D272D693A41A05405405430D95E80"; 128 | assertEquals("encoded hex not equal", expectedHex, 129 | UperEncoder.hexStringFromBytes(encoded)); 130 | 131 | Cam decoded = UperEncoder.decode(encoded, Cam.class); 132 | logger.debug("(test) decoded object: {}", decoded); 133 | byte[] reencoded = UperEncoder.encode(decoded); 134 | logger.debug("reencodedChoice2 data hex: {}", UperEncoder.hexStringFromBytes(reencoded)); 135 | assertEquals("reencoded hex not equal", expectedHex, 136 | UperEncoder.hexStringFromBytes(reencoded)); 137 | } 138 | 139 | @Test public void bitstringTest1() { 140 | Object pdu = DrivingLaneStatus.builder().outermostLaneClosed(true).setBit(3, true).create(); 141 | byte[] encoded = UperEncoder.encode(pdu); 142 | logger.debug("encoded bitstring data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 143 | 144 | Object decoded = UperEncoder.decode(encoded, DrivingLaneStatus.class); 145 | byte[] reencoded = UperEncoder.encode(decoded); 146 | assertArrayEquals("encoded and reencoded", encoded, reencoded); 147 | } 148 | 149 | /** 150 | *
151 | PosPillar ::= INTEGER {tenCentimeters(1), unavailable(30)} (1..30)
152 | PositionOfPillars ::= SEQUENCE (SIZE(1..3, ...)) OF PosPillar
153 |      *  
GCDC 32 | * 33 | * 34 | * This implementation was partly developed within i-GAME project that has received funding from the 35 | * European Union's Seventh Framework Programme for research, technological development and demonstration 36 | * under grant agreement no 612035. 37 | * 38 | */ 39 | public final class Iclcm { 40 | /** 41 | * MessageID of i-GAME cooperative lane change message 42 | */ 43 | public static final int MessageID_iCLCM = 10; 44 | private Iclcm(){} 45 | 46 | @Sequence 47 | public static class IgameCooperativeLaneChangeMessage { 48 | ItsPduHeader header; 49 | IgameCooperativeLaneChangeMessageBody iclm; 50 | 51 | public IgameCooperativeLaneChangeMessage(ItsPduHeader itsPduHeader, IgameCooperativeLaneChangeMessageBody iclm) { 52 | this.header = itsPduHeader; 53 | this.iclm = iclm; 54 | } 55 | 56 | public IgameCooperativeLaneChangeMessage() { 57 | this( 58 | new ItsPduHeader(new ProtocolVersion(1),new MessageId(MessageID_iCLCM),new StationID()), 59 | new IgameCooperativeLaneChangeMessageBody() 60 | ); 61 | } 62 | 63 | @Override public String toString() { return "IgameCooperativeLaneChangeMessage(" + header + ", " + iclm + ")"; } 64 | 65 | public ItsPduHeader getHeader() { 66 | return header; 67 | } 68 | 69 | public IgameCooperativeLaneChangeMessageBody getIclm() { 70 | return iclm; 71 | } 72 | } 73 | @Sequence 74 | public static class IgameCooperativeLaneChangeMessageBody { 75 | GenerationDeltaTime generationDeltaTime; 76 | IclmParameters iclmParameters; 77 | 78 | public IgameCooperativeLaneChangeMessageBody(GenerationDeltaTime generationDeltaTime,IclmParameters iclmParameters){ 79 | this.generationDeltaTime = generationDeltaTime; 80 | this.iclmParameters = iclmParameters; 81 | } 82 | public IgameCooperativeLaneChangeMessageBody(){ 83 | this(new GenerationDeltaTime(),new IclmParameters()); 84 | } 85 | @Override public String toString() { return "IgameCooperativeLaneChangeMessageBody(" + generationDeltaTime + ", " + iclmParameters + ")"; } 86 | public GenerationDeltaTime getGenerationDeltaTime() { 87 | return generationDeltaTime; 88 | } 89 | public IclmParameters getIclmParameters() { 90 | return iclmParameters; 91 | } 92 | } 93 | @Sequence 94 | public static class IclmParameters { 95 | VehicleContainerHighFrequency vehicleContainerHighFrequency; 96 | @Asn1Optional VehicleContainerLowFrequency lowFrequencyContainer; 97 | MostImportantObjectContainer mostImportantObjectContainer; 98 | LaneObject laneObject; 99 | PairIdObject pairIdObject; 100 | MergeObject mergeObject; 101 | ScenarioObject scenarioObject; 102 | 103 | public IclmParameters(VehicleContainerHighFrequency vehicleContainerHighFrequency, 104 | VehicleContainerLowFrequency lowFrequencyContainer, 105 | MostImportantObjectContainer mostImportantObjectContainer, 106 | LaneObject laneObject, 107 | PairIdObject pairIdObject, 108 | MergeObject mergeObject, 109 | ScenarioObject scenarioObject){ 110 | this.vehicleContainerHighFrequency=vehicleContainerHighFrequency; 111 | this.lowFrequencyContainer=lowFrequencyContainer; 112 | this.mostImportantObjectContainer=mostImportantObjectContainer; 113 | this.laneObject=laneObject; 114 | this.pairIdObject=pairIdObject; 115 | this.mergeObject=mergeObject; 116 | this.scenarioObject=scenarioObject; 117 | } 118 | public IclmParameters(){ 119 | this(new VehicleContainerHighFrequency(),null, 120 | new MostImportantObjectContainer(),new LaneObject(),new PairIdObject(), 121 | new MergeObject(),new ScenarioObject()); 122 | } 123 | @Override public String toString() { return "IclmParameters(" + vehicleContainerHighFrequency + ", " 124 | + lowFrequencyContainer + ", " + mostImportantObjectContainer + ", " + laneObject + ", " 125 | + pairIdObject + ", " + mergeObject + ", " + scenarioObject + ")"; } 126 | public VehicleContainerHighFrequency getVehicleContainerHighFrequency() { 127 | return vehicleContainerHighFrequency; 128 | } 129 | public boolean hasLowFrequencyContainer() { 130 | return lowFrequencyContainer != null; 131 | } 132 | public VehicleContainerLowFrequency getLowFrequencyContainer() { 133 | return lowFrequencyContainer; 134 | } 135 | public MostImportantObjectContainer getMostImportantObjectContainer() { 136 | return mostImportantObjectContainer; 137 | } 138 | public LaneObject getLaneObject() { 139 | return laneObject; 140 | } 141 | public PairIdObject getPairIdObject() { 142 | return pairIdObject; 143 | } 144 | public MergeObject getMergeObject() { 145 | return mergeObject; 146 | } 147 | public ScenarioObject getScenarioObject() { 148 | return scenarioObject; 149 | } 150 | } 151 | @Sequence 152 | public static class VehicleContainerHighFrequency{ 153 | VehicleRearAxleLocation vehicleRearAxleLocation; 154 | ControllerType controllerType; 155 | VehicleResponseTime vehicleResponseTime; 156 | TargetLongitudonalAcceleration targetLongitudinalAcceleration; 157 | TimeHeadway timeHeadway; 158 | CruiseSpeed cruisespeed; 159 | 160 | public VehicleContainerHighFrequency(){ 161 | this(new VehicleRearAxleLocation(),new ControllerType(), 162 | new VehicleResponseTime(), new TargetLongitudonalAcceleration(), new TimeHeadway(), new CruiseSpeed()); 163 | } 164 | 165 | public VehicleContainerHighFrequency(VehicleRearAxleLocation vehicleRearAxleLocation,ControllerType controllerType, 166 | VehicleResponseTime vehicleResponseTime,TargetLongitudonalAcceleration targetLongitudinalAcceleration, 167 | TimeHeadway timeHeadway,CruiseSpeed cruisespeed){ 168 | this.vehicleRearAxleLocation = vehicleRearAxleLocation; 169 | this.controllerType = controllerType; 170 | this.vehicleResponseTime = vehicleResponseTime; 171 | this.targetLongitudinalAcceleration = targetLongitudinalAcceleration; 172 | this.timeHeadway = timeHeadway; 173 | this.cruisespeed = cruisespeed; 174 | } 175 | 176 | @Override public String toString() { return "VehicleContainerHighFrequency(" + vehicleRearAxleLocation + ", " 177 | + controllerType + ", " + vehicleResponseTime + ", " + targetLongitudinalAcceleration + ", " 178 | + timeHeadway + ", " + cruisespeed + ")"; } 179 | 180 | public VehicleRearAxleLocation getVehicleRearAxleLocation() { 181 | return vehicleRearAxleLocation; 182 | } 183 | 184 | public ControllerType getControllerType() { 185 | return controllerType; 186 | } 187 | 188 | public VehicleResponseTime getVehicleResponseTime() { 189 | return vehicleResponseTime; 190 | } 191 | 192 | public TargetLongitudonalAcceleration getTargetLongitudinalAcceleration() { 193 | return targetLongitudinalAcceleration; 194 | } 195 | 196 | public TimeHeadway getTimeHeadway() { 197 | return timeHeadway; 198 | } 199 | 200 | public CruiseSpeed getCruisespeed() { 201 | return cruisespeed; 202 | } 203 | } 204 | @Sequence 205 | public static class VehicleContainerLowFrequency{ 206 | @Asn1Optional ParticipantsReady participantsReady; 207 | @Asn1Optional StartPlatoon startPlatoon; 208 | @Asn1Optional EndOfScenario endOfScenario; 209 | public VehicleContainerLowFrequency(){}//Fully optional 210 | public VehicleContainerLowFrequency(ParticipantsReady participantsReady){this.participantsReady = participantsReady;} 211 | public VehicleContainerLowFrequency(StartPlatoon startPlatoon){this.startPlatoon = startPlatoon;} 212 | public VehicleContainerLowFrequency(EndOfScenario endOfScenario){this.endOfScenario = endOfScenario;} 213 | 214 | @Override public String toString() { return "VehicleContainerLowFrequency(" 215 | +" participantsReady= "+(participantsReady!= null? participantsReady : "null") 216 | +", startPlatoon= "+(startPlatoon!= null? startPlatoon : "null") 217 | +", endOfScenario= "+(endOfScenario!= null? endOfScenario : "null") 218 | +")";}; 219 | 220 | public static Builder builder() { return new Builder(); } 221 | 222 | public static class Builder{ 223 | private VehicleContainerLowFrequency val = new VehicleContainerLowFrequency(); 224 | private boolean created = false; 225 | private void checkCreated() { 226 | if (created) { throw new IllegalStateException("Already created"); } 227 | } 228 | public VehicleContainerLowFrequency create() { created = true; return val; } 229 | 230 | public Builder participantsReady(ParticipantsReady participantsReady) { checkCreated(); val.participantsReady = participantsReady; return this; } 231 | public Builder startPlatoon(StartPlatoon startPlatoon) { checkCreated(); val.startPlatoon = startPlatoon; return this; } 232 | public Builder endOfScenario(EndOfScenario endOfScenario) { checkCreated(); val.endOfScenario = endOfScenario; return this; } 233 | } 234 | 235 | public boolean hasParticipantsReady(){ 236 | return participantsReady!=null; 237 | } 238 | public ParticipantsReady getParticipantsReady() { 239 | return participantsReady; 240 | } 241 | public boolean hasStartPlatoon(){ 242 | return startPlatoon!=null; 243 | } 244 | public StartPlatoon getStartPlatoon() { 245 | return startPlatoon; 246 | } 247 | public boolean hasEndOfScenario(){ 248 | return endOfScenario!=null; 249 | } 250 | public EndOfScenario getEndOfScenario() { 251 | return endOfScenario; 252 | } 253 | } 254 | @Sequence 255 | public static class MostImportantObjectContainer{ 256 | StationID mioID; 257 | MioRange mioRange; 258 | MioBearing mioBearing; 259 | MioRangeRate mioRangeRate; 260 | public MostImportantObjectContainer(){this( new StationID(), new MioRange(), new MioBearing(), new MioRangeRate() );} 261 | public MostImportantObjectContainer(StationID mioID,MioRange mioRange,MioBearing mioBearing,MioRangeRate mioRangeRate){ 262 | this.mioID = mioID; 263 | this.mioRange = mioRange; 264 | this.mioBearing = mioBearing; 265 | this.mioRangeRate = mioRangeRate; 266 | } 267 | public StationID getMioID() { 268 | return mioID; 269 | } 270 | public MioRange getMioRange() { 271 | return mioRange; 272 | } 273 | public MioBearing getMioBearing() { 274 | return mioBearing; 275 | } 276 | public MioRangeRate getMioRangeRate() { 277 | return mioRangeRate; 278 | } 279 | 280 | @Override public String toString() { return "MostImportantObjectContainer(" + mioID + ", " + mioRange + ", " + mioBearing + ", " +mioRangeRate + ")"; } 281 | } 282 | @Sequence 283 | public static class LaneObject{ 284 | Lane lane; 285 | public LaneObject(){this(new Lane());} 286 | public LaneObject(Lane lane){this.lane = lane;} 287 | public Lane getLane() { 288 | return lane; 289 | } 290 | @Override public String toString() { return "LaneObject(" + lane + ")"; } 291 | } 292 | 293 | @Sequence 294 | public static class PairIdObject{ 295 | StationID forwardID; 296 | StationID backwardID; 297 | AcknowledgeFlag acknowledgeFlag; 298 | public PairIdObject(){this(new StationID(),new StationID(), new AcknowledgeFlag());} 299 | public PairIdObject(StationID forwardID, StationID backwardID, AcknowledgeFlag acknowledgeFlag){ 300 | this.forwardID = forwardID; 301 | this.backwardID = backwardID; 302 | this.acknowledgeFlag = acknowledgeFlag; 303 | } 304 | public StationID getForwardID() { 305 | return forwardID; 306 | } 307 | public StationID getBackwardID() { 308 | return backwardID; 309 | } 310 | public AcknowledgeFlag getAcknowledgeFlag() { 311 | return acknowledgeFlag; 312 | } 313 | 314 | @Override public String toString() { return "PairIdObject(" + forwardID +", "+backwardID+", "+acknowledgeFlag+ ")"; } 315 | } 316 | 317 | @Sequence 318 | public static class MergeObject{ 319 | MergeRequest mergeRequest; 320 | MergeSafeToMerge mergeSafeToMerge; 321 | MergeFlag mergeFlag; 322 | MergeFlagTail mergeFlagTail; 323 | MergeFlagHead mergeFlagHead; 324 | 325 | public MergeObject(){this(new MergeRequest(),new MergeSafeToMerge(),new MergeFlag(),new MergeFlagTail(),new MergeFlagHead());} 326 | public MergeObject(MergeRequest mergeRequest,MergeSafeToMerge mergeSafeToMerge,MergeFlag mergeFlag,MergeFlagTail mergeFlagTail,MergeFlagHead mergeFlagHead){ 327 | this.mergeRequest = mergeRequest; 328 | this.mergeSafeToMerge = mergeSafeToMerge; 329 | this.mergeFlag = mergeFlag; 330 | this.mergeFlagTail = mergeFlagTail; 331 | this.mergeFlagHead = mergeFlagHead; 332 | } 333 | public MergeRequest getMergeRequest() { 334 | return mergeRequest; 335 | } 336 | public MergeSafeToMerge getMergeSafeToMerge() { 337 | return mergeSafeToMerge; 338 | } 339 | public MergeFlag getMergeFlag() { 340 | return mergeFlag; 341 | } 342 | public MergeFlagTail getMergeFlagTail() { 343 | return mergeFlagTail; 344 | } 345 | public MergeFlagHead getMergeFlagHead() { 346 | return mergeFlagHead; 347 | } 348 | @Override public String toString() { return "MergeObject(" + mergeRequest +", "+mergeSafeToMerge+", "+mergeFlag+ ", "+mergeFlagTail+", "+mergeFlagHead+ ")"; } 349 | 350 | } 351 | @Sequence 352 | public static class ScenarioObject{ 353 | PlatoonID platoonID; 354 | DistanceTravelledCZ distanceTravelledCZ; 355 | Intention intention; 356 | Counter counterIntersection; 357 | 358 | public ScenarioObject(){this(new PlatoonID(), new DistanceTravelledCZ(), new Intention(), new Counter());} 359 | public ScenarioObject(PlatoonID platoonID,DistanceTravelledCZ distanceTravelledCZ,Intention intention,Counter counterIntersection){ 360 | this.platoonID = platoonID; 361 | this.distanceTravelledCZ = distanceTravelledCZ; 362 | this.intention = intention; 363 | this.counterIntersection = counterIntersection; 364 | } 365 | public PlatoonID getPlatoonID() { 366 | return platoonID; 367 | } 368 | public DistanceTravelledCZ getDistanceTravelledCZ() { 369 | return distanceTravelledCZ; 370 | } 371 | public Intention getIntention() { 372 | return intention; 373 | } 374 | public Counter getCounterIntersection() { 375 | return counterIntersection; 376 | } 377 | @Override public String toString() { return "ScenarioObject(" + platoonID +", "+distanceTravelledCZ+", "+intention+ ", "+counterIntersection+ ")"; } 378 | } 379 | 380 | @Sequence 381 | public static class VehicleResponseTime{ 382 | VehicleResponseTimeConstant vehicleResponseTimeConstant; 383 | VehicleResponseTimeDelay vehicleResponseTimeDelay; 384 | public VehicleResponseTime(){this(new VehicleResponseTimeConstant(),new VehicleResponseTimeDelay());} 385 | public VehicleResponseTime(VehicleResponseTimeConstant vehicleResponseTimeConstant,VehicleResponseTimeDelay vehicleResponseTimeDelay ){ 386 | this.vehicleResponseTimeConstant = vehicleResponseTimeConstant; 387 | this.vehicleResponseTimeDelay = vehicleResponseTimeDelay; 388 | } 389 | public VehicleResponseTimeConstant getVehicleResponseTimeConstant() { 390 | return vehicleResponseTimeConstant; 391 | } 392 | public VehicleResponseTimeDelay getVehicleResponseTimeDelay() { 393 | return vehicleResponseTimeDelay; 394 | } 395 | @Override public String toString() { return "VehicleResponseTime(" + vehicleResponseTimeConstant +", "+vehicleResponseTimeDelay+")"; } 396 | } 397 | 398 | @IntRange(minValue = 0, maxValue = 4095) 399 | public static class VehicleRearAxleLocation extends Asn1Integer { 400 | public static final int oneMeter = 100; 401 | 402 | public VehicleRearAxleLocation() { this(0); } 403 | public VehicleRearAxleLocation(int value) { super(value); } 404 | } 405 | 406 | @IntRange(minValue = 0, maxValue = 3) 407 | public static class ControllerType extends Asn1Integer { 408 | public static final int manual = 0; 409 | public static final int cc = 1; 410 | public static final int acc = 2; 411 | public static final int cacc = 3; 412 | 413 | public ControllerType() { this(manual); } 414 | public ControllerType(int value) { super(value); } 415 | 416 | @Override public String toString() { 417 | switch((int)value){ 418 | case manual: return "manual"; 419 | case cc: return "cc"; 420 | case acc: return "acc"; 421 | case cacc: return "cacc"; 422 | default: return "Unkown"; 423 | } 424 | } 425 | } 426 | 427 | @IntRange(minValue = 0, maxValue = 1001) 428 | public static class VehicleResponseTimeConstant extends Asn1Integer { 429 | public static final int oneSecond = 100; 430 | public static final int unavailable = 1001; 431 | 432 | public VehicleResponseTimeConstant() { this(unavailable); } 433 | public VehicleResponseTimeConstant(int value) { super(value); } 434 | } 435 | 436 | @IntRange(minValue = 0, maxValue = 1001) 437 | public static class VehicleResponseTimeDelay extends Asn1Integer { 438 | public static final int oneSecond = 100; 439 | public static final int unavailable = 1001; 440 | 441 | public VehicleResponseTimeDelay() { this(unavailable); } 442 | public VehicleResponseTimeDelay(int value) { super(value); } 443 | } 444 | 445 | @IntRange(minValue = -1000, maxValue = 1001) 446 | public static class TargetLongitudonalAcceleration extends Asn1Integer { 447 | public static final int oneMeterPerSecondSquared = 100; 448 | public static final int unavailable = 1001; 449 | 450 | public TargetLongitudonalAcceleration() { this(unavailable); } 451 | public TargetLongitudonalAcceleration(int value) { super(value); } 452 | } 453 | 454 | @IntRange(minValue = 0, maxValue = 65535) 455 | public static class MioRange extends Asn1Integer { 456 | public static final int oneMeter = 100; 457 | public static final int unavailable = 65535; 458 | 459 | public MioRange() { this(unavailable); } 460 | public MioRange(int value) { super(value); } 461 | } 462 | 463 | @IntRange(minValue = -1571, maxValue = 1572) 464 | public static class MioBearing extends Asn1Integer { 465 | public static final int zeroRadians = 0; 466 | public static final int oneRadianRight = 500; 467 | public static final int unavailable = 1572; 468 | 469 | public MioBearing() { this(unavailable); } 470 | public MioBearing(int value) { super(value); } 471 | } 472 | 473 | @IntRange(minValue = -32767, maxValue = 32767) 474 | public static class MioRangeRate extends Asn1Integer { 475 | public static final int zeroMeterPerSecond = 0; 476 | public static final int oneMeterPerSecond = 100; 477 | public static final int unavailable = 32767; 478 | 479 | public MioRangeRate() { this(unavailable); } 480 | public MioRangeRate(int value) { super(value); } 481 | } 482 | 483 | @IntRange(minValue = 0, maxValue = 361) 484 | public static class TimeHeadway extends Asn1Integer { 485 | public static final int oneSecond = 10; 486 | public static final int unavailable = 361; 487 | 488 | public TimeHeadway() { this(unavailable); } 489 | public TimeHeadway(int value) { super(value); } 490 | } 491 | 492 | @IntRange(minValue = 0, maxValue = 5001) 493 | public static class CruiseSpeed extends Asn1Integer { 494 | public static final int oneMeterPerSecond = 100; 495 | public static final int unavailable = 5001; 496 | 497 | public CruiseSpeed() { this(unavailable); } 498 | public CruiseSpeed(int value) { super(value); } 499 | } 500 | 501 | @IntRange(minValue = 0, maxValue = 1) 502 | public static class MergeRequest extends Asn1Integer { 503 | public static final int noMergeRequest = 0; 504 | public static final int mergeRequest = 1; 505 | 506 | public MergeRequest() { this(noMergeRequest); } 507 | public MergeRequest(int value) { super(value); } 508 | @Override public String toString(){ return value==noMergeRequest?"MergeRequest(no)":"MergeRequest(yes)";} 509 | } 510 | 511 | @IntRange(minValue = 0, maxValue = 1) 512 | public static class MergeSafeToMerge extends Asn1Integer { 513 | public static final int notSafe = 0; 514 | public static final int safe = 1; 515 | 516 | public MergeSafeToMerge() { this(notSafe); } 517 | public MergeSafeToMerge(int value) { super(value); } 518 | 519 | @Override public String toString(){ return value==notSafe?"MergeSafeToMerge(not safe)":"MergeSafeToMerge(safe)";} 520 | } 521 | 522 | @IntRange(minValue = 0, maxValue = 1) 523 | public static class MergeFlag extends Asn1Integer { 524 | public static final int notMergeReady = 0; 525 | public static final int mergeReady = 1; 526 | 527 | public MergeFlag() { this(notMergeReady); } 528 | public MergeFlag(int value) { super(value); } 529 | } 530 | 531 | @IntRange(minValue = 0, maxValue = 1) 532 | public static class MergeFlagTail extends Asn1Integer { 533 | public static final int notLastVehicle = 0; 534 | public static final int lastVehicle = 1; 535 | 536 | public MergeFlagTail() { this(notLastVehicle); } 537 | public MergeFlagTail(int value) { super(value); } 538 | } 539 | 540 | @IntRange(minValue = 0, maxValue = 1) 541 | public static class MergeFlagHead extends Asn1Integer { 542 | public static final int notFirstVehicle = 0; 543 | public static final int firstVehicle = 1; 544 | 545 | public MergeFlagHead() { this(notFirstVehicle); } 546 | public MergeFlagHead(int value) { super(value); } 547 | } 548 | 549 | @IntRange(minValue = 0, maxValue = 255) 550 | public static class PlatoonID extends Asn1Integer { 551 | public static final int platoonA = 1; 552 | public static final int platoonB = 2; 553 | public static final int notUsed = 3; 554 | 555 | public PlatoonID() { this(notUsed); } 556 | public PlatoonID(int value) { super(value); } 557 | } 558 | 559 | @IntRange(minValue = 0, maxValue = 10000) 560 | public static class DistanceTravelledCZ extends Asn1Integer { 561 | public static final int oneMeter = 10; 562 | 563 | public DistanceTravelledCZ() { this(0); } 564 | public DistanceTravelledCZ(int value) { super(value); } 565 | } 566 | 567 | @IntRange(minValue = 1, maxValue = 3) 568 | public static class Intention extends Asn1Integer { 569 | public static final int straightNoTurning = 1; 570 | public static final int turnLeft = 2; 571 | public static final int turnRight = 3; 572 | 573 | public Intention() { this(straightNoTurning); } 574 | public Intention(int value) { super(value); } 575 | } 576 | 577 | @IntRange(minValue = 1, maxValue = 4) 578 | public static class Lane extends Asn1Integer { 579 | public static final int laneOne = 1; 580 | public static final int laneTwo = 2; 581 | public static final int laneThree = 3; 582 | public static final int unavailable = 4; 583 | 584 | public Lane() { this(unavailable); } 585 | public Lane(int value) { super(value); } 586 | } 587 | 588 | @IntRange(minValue = 0, maxValue = 3) 589 | public static class Counter extends Asn1Integer { 590 | public static final int noVehicles = 0; 591 | public static final int oneVehicle = 1; 592 | 593 | public Counter() { this(noVehicles); } 594 | public Counter(int value) { super(value); } 595 | } 596 | 597 | @IntRange(minValue = 0, maxValue = 1) 598 | public static class AcknowledgeFlag extends Asn1Integer { 599 | public static final int acknowledged = 1; 600 | public static final int notAcknowledged = 0; 601 | 602 | public AcknowledgeFlag() { this(notAcknowledged); } 603 | public AcknowledgeFlag(int value) { super(value); } 604 | } 605 | 606 | @IntRange(minValue = 0, maxValue = 1) 607 | public static class ParticipantsReady extends Asn1Integer { 608 | public static final int notReady = 0; 609 | public static final int ready =1; 610 | 611 | public ParticipantsReady() { this(notReady); } 612 | public ParticipantsReady(int value) { super(value); } 613 | } 614 | 615 | @IntRange(minValue = 0, maxValue = 1) 616 | public static class StartPlatoon extends Asn1Integer { 617 | public static final int startPlatoonAAtSpeed80kph = 0; 618 | public static final int startPlatoonBAtSpeed60kph = 1; 619 | 620 | public StartPlatoon() { this(startPlatoonAAtSpeed80kph); } 621 | public StartPlatoon(int value) { super(value); } 622 | } 623 | 624 | @IntRange(minValue = 1, maxValue = 1) 625 | public static class EndOfScenario extends Asn1Integer { 626 | public static final int endOfScenario = 1; 627 | 628 | public EndOfScenario() { this(endOfScenario); } 629 | public EndOfScenario(int value) { super(value); } 630 | } 631 | 632 | } 633 | 634 | -------------------------------------------------------------------------------- /src/test/java/net/gcdc/camdenm/CoopItsTest.java: -------------------------------------------------------------------------------- 1 | package net.gcdc.camdenm; 2 | 3 | import static org.junit.Assert.assertArrayEquals; 4 | import static org.junit.Assert.assertEquals; 5 | import static org.junit.Assert.fail; 6 | 7 | import java.util.Arrays; 8 | 9 | import net.gcdc.asn1.uper.UperEncoder; 10 | import net.gcdc.camdenm.CoopIts; 11 | import net.gcdc.camdenm.CoopIts.AccelerationControl; 12 | import net.gcdc.camdenm.CoopIts.ActionID; 13 | import net.gcdc.camdenm.CoopIts.AlacarteContainer; 14 | import net.gcdc.camdenm.CoopIts.Altitude; 15 | import net.gcdc.camdenm.CoopIts.AltitudeConfidence; 16 | import net.gcdc.camdenm.CoopIts.AltitudeValue; 17 | import net.gcdc.camdenm.CoopIts.BasicContainer; 18 | import net.gcdc.camdenm.CoopIts.BasicVehicleContainerHighFrequency; 19 | import net.gcdc.camdenm.CoopIts.BasicVehicleContainerLowFrequency; 20 | import net.gcdc.camdenm.CoopIts.CamParameters; 21 | import net.gcdc.camdenm.CoopIts.CauseCode; 22 | import net.gcdc.camdenm.CoopIts.CauseCodeType; 23 | import net.gcdc.camdenm.CoopIts.ClosedLanes; 24 | import net.gcdc.camdenm.CoopIts.CoopAwareness; 25 | import net.gcdc.camdenm.CoopIts.DangerousGoodsBasic; 26 | import net.gcdc.camdenm.CoopIts.DangerousGoodsExtended; 27 | import net.gcdc.camdenm.CoopIts.DecentralizedEnvironmentalNotificationMessage; 28 | import net.gcdc.camdenm.CoopIts.DeltaAltitude; 29 | import net.gcdc.camdenm.CoopIts.DeltaLatitude; 30 | import net.gcdc.camdenm.CoopIts.DeltaLongitude; 31 | import net.gcdc.camdenm.CoopIts.DeltaReferencePosition; 32 | import net.gcdc.camdenm.CoopIts.DrivingLaneStatus; 33 | import net.gcdc.camdenm.CoopIts.EnergyStorageType; 34 | import net.gcdc.camdenm.CoopIts.EventHistory; 35 | import net.gcdc.camdenm.CoopIts.EventPoint; 36 | import net.gcdc.camdenm.CoopIts.ExteriorLights; 37 | import net.gcdc.camdenm.CoopIts.HardShoulderStatus; 38 | import net.gcdc.camdenm.CoopIts.Heading; 39 | import net.gcdc.camdenm.CoopIts.HeadingConfidence; 40 | import net.gcdc.camdenm.CoopIts.HeadingValue; 41 | import net.gcdc.camdenm.CoopIts.HeightLonCarr; 42 | import net.gcdc.camdenm.CoopIts.HighFrequencyContainer; 43 | import net.gcdc.camdenm.CoopIts.ImpactReductionContainer; 44 | import net.gcdc.camdenm.CoopIts.InformationQuality; 45 | import net.gcdc.camdenm.CoopIts.ItineraryPath; 46 | import net.gcdc.camdenm.CoopIts.ItsPduHeader; 47 | import net.gcdc.camdenm.CoopIts.ItsPduHeader.MessageId; 48 | import net.gcdc.camdenm.CoopIts.LanePosition; 49 | import net.gcdc.camdenm.CoopIts.Latitude; 50 | import net.gcdc.camdenm.CoopIts.LightBarSirenInUse; 51 | import net.gcdc.camdenm.CoopIts.LocationContainer; 52 | import net.gcdc.camdenm.CoopIts.Longitude; 53 | import net.gcdc.camdenm.CoopIts.LowFrequencyContainer; 54 | import net.gcdc.camdenm.CoopIts.ManagementContainer; 55 | import net.gcdc.camdenm.CoopIts.NumberOfOccupants; 56 | import net.gcdc.camdenm.CoopIts.PathDeltaTime; 57 | import net.gcdc.camdenm.CoopIts.PathHistory; 58 | import net.gcdc.camdenm.CoopIts.PathPoint; 59 | import net.gcdc.camdenm.CoopIts.PosCentMass; 60 | import net.gcdc.camdenm.CoopIts.PosConfidenceEllipse; 61 | import net.gcdc.camdenm.CoopIts.PosFrontAx; 62 | import net.gcdc.camdenm.CoopIts.PosLonCarr; 63 | import net.gcdc.camdenm.CoopIts.PosPillar; 64 | import net.gcdc.camdenm.CoopIts.PositionOfOccupants; 65 | import net.gcdc.camdenm.CoopIts.PositionOfPillars; 66 | import net.gcdc.camdenm.CoopIts.PositioningSolutionType; 67 | import net.gcdc.camdenm.CoopIts.PtActivation; 68 | import net.gcdc.camdenm.CoopIts.PtActivationData; 69 | import net.gcdc.camdenm.CoopIts.PtActivationType; 70 | import net.gcdc.camdenm.CoopIts.PublicTransportContainer; 71 | import net.gcdc.camdenm.CoopIts.ReferenceDenms; 72 | import net.gcdc.camdenm.CoopIts.ReferencePosition; 73 | import net.gcdc.camdenm.CoopIts.RelevanceDistance; 74 | import net.gcdc.camdenm.CoopIts.RelevanceTrafficDirection; 75 | import net.gcdc.camdenm.CoopIts.RequestResponseIndication; 76 | import net.gcdc.camdenm.CoopIts.RestrictedTypes; 77 | import net.gcdc.camdenm.CoopIts.RoadType; 78 | import net.gcdc.camdenm.CoopIts.RoadWorksContainerBasic; 79 | import net.gcdc.camdenm.CoopIts.RoadWorksContainerExtended; 80 | import net.gcdc.camdenm.CoopIts.SemiAxisLength; 81 | import net.gcdc.camdenm.CoopIts.SequenceNumber; 82 | import net.gcdc.camdenm.CoopIts.SituationContainer; 83 | import net.gcdc.camdenm.CoopIts.SpecialVehicleContainer; 84 | import net.gcdc.camdenm.CoopIts.Speed; 85 | import net.gcdc.camdenm.CoopIts.SpeedConfidence; 86 | import net.gcdc.camdenm.CoopIts.SpeedLimit; 87 | import net.gcdc.camdenm.CoopIts.SpeedValue; 88 | import net.gcdc.camdenm.CoopIts.StationID; 89 | import net.gcdc.camdenm.CoopIts.StationType; 90 | import net.gcdc.camdenm.CoopIts.StationarySince; 91 | import net.gcdc.camdenm.CoopIts.StationaryVehicleContainer; 92 | import net.gcdc.camdenm.CoopIts.SubCauseCodeType; 93 | import net.gcdc.camdenm.CoopIts.Temperature; 94 | import net.gcdc.camdenm.CoopIts.Termination; 95 | import net.gcdc.camdenm.CoopIts.TimestampIts; 96 | import net.gcdc.camdenm.CoopIts.Traces; 97 | import net.gcdc.camdenm.CoopIts.TrafficRule; 98 | import net.gcdc.camdenm.CoopIts.TransmissionInterval; 99 | import net.gcdc.camdenm.CoopIts.TurningRadius; 100 | import net.gcdc.camdenm.CoopIts.VDS; 101 | import net.gcdc.camdenm.CoopIts.ValidityDuration; 102 | import net.gcdc.camdenm.CoopIts.VehicleIdentification; 103 | import net.gcdc.camdenm.CoopIts.VehicleMass; 104 | import net.gcdc.camdenm.CoopIts.VehicleRole; 105 | import net.gcdc.camdenm.CoopIts.WMInumber; 106 | import net.gcdc.camdenm.CoopIts.WheelBaseVehicle; 107 | 108 | import org.junit.Test; 109 | import org.slf4j.Logger; 110 | import org.slf4j.LoggerFactory; 111 | 112 | public class CoopItsTest { 113 | private final static Logger logger = LoggerFactory.getLogger(UperEncoder.class); 114 | 115 | @Test public void test() { 116 | //List bitlist = Arrays.asList(true, false); 117 | //byte[] bytes = UperEncoder.boolToBits(Arrays.asList(true, false)); 118 | 119 | assertArrayEquals(new byte[] { 127 }, UperEncoder.bytesFromCollection(Arrays.asList(false, true, true, true, true, true, true, true))); 120 | assertArrayEquals(new byte[] { 2 }, UperEncoder.bytesFromCollection(Arrays.asList(false, false, false, false, false, false, true, false))); 121 | assertArrayEquals(new byte[] { 127, 2 }, UperEncoder.bytesFromCollection(Arrays.asList(false, true, true, true, true, true, true, true, false, false, false, false, false, false, true, false))); 122 | assertArrayEquals(new byte[] { 32 }, UperEncoder.bytesFromCollection(Arrays.asList(false, false, true))); 123 | } 124 | 125 | @Test public void test2() throws IllegalArgumentException, IllegalAccessException { 126 | CoopIts.Cam cam = new CoopIts.Cam(); 127 | 128 | byte[] encoded = UperEncoder.encode(cam); 129 | 130 | logger.debug("data: {}", encoded); 131 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 132 | logger.debug("data bin: {}", UperEncoder.binaryStringFromBytes(encoded)); 133 | assertEquals("0102000000000064000D693A403AD274803FFFFFFC23B7743E00E11FDFFFFEBFE9ED0737530F5FFFB0", 134 | UperEncoder.hexStringFromBytes(encoded)); 135 | } 136 | 137 | @Test public void test3() throws IllegalArgumentException, IllegalAccessException { 138 | 139 | CoopIts.Cam cam = 140 | new CoopIts.Cam( 141 | new ItsPduHeader(new MessageId(MessageId.cam)), 142 | new CoopAwareness( 143 | new CoopIts.GenerationDeltaTime(100), 144 | new CamParameters( 145 | new BasicContainer( 146 | new StationType(CoopIts.StationType.unknown), 147 | new ReferencePosition( 148 | new Latitude(57), 149 | new Longitude(13), 150 | new PosConfidenceEllipse( 151 | new SemiAxisLength(SemiAxisLength.unavailable), 152 | new SemiAxisLength(), 153 | new HeadingValue(HeadingValue.unavailable)), 154 | new Altitude( 155 | new AltitudeValue(AltitudeValue.unavailable), 156 | AltitudeConfidence.unavailable))), 157 | new HighFrequencyContainer( 158 | BasicVehicleContainerHighFrequency.builder() 159 | .accelerationControl(AccelerationControl.builder() 160 | .accEngaged(true) 161 | .gasPedalEngaged(true) 162 | .create()) 163 | .create())))); 164 | 165 | byte[] encoded = UperEncoder.encode(cam); 166 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 167 | assertEquals("01020000000000640006B49D272D693A41BFFFFFFC23B7743E40E11FDFFFFEBFE9ED0737530F5FFFB090", 168 | UperEncoder.hexStringFromBytes(encoded)); 169 | } 170 | 171 | @Test public void test4() throws IllegalArgumentException, IllegalAccessException { 172 | CoopIts.Cam cam = 173 | new CoopIts.Cam( 174 | new ItsPduHeader(new MessageId(MessageId.cam)), 175 | new CoopAwareness( 176 | new CoopIts.GenerationDeltaTime(100), 177 | new CamParameters( 178 | new BasicContainer( 179 | new StationType(CoopIts.StationType.unknown), 180 | new ReferencePosition( 181 | new Latitude(57), 182 | new Longitude(13), 183 | new PosConfidenceEllipse( 184 | new SemiAxisLength(SemiAxisLength.unavailable), 185 | new SemiAxisLength(), 186 | new HeadingValue(HeadingValue.unavailable)), 187 | new Altitude( 188 | new AltitudeValue(AltitudeValue.unavailable), 189 | AltitudeConfidence.unavailable))), 190 | new HighFrequencyContainer( 191 | BasicVehicleContainerHighFrequency.builder() 192 | .accelerationControl(AccelerationControl.builder() 193 | .accEngaged(true) 194 | .gasPedalEngaged(true) 195 | .create()) 196 | .create()), 197 | new LowFrequencyContainer( 198 | new BasicVehicleContainerLowFrequency( 199 | VehicleRole.default_, 200 | ExteriorLights.builder().create(), 201 | new PathHistory( 202 | new PathPoint(), 203 | new PathPoint()))), 204 | null))); 205 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(UperEncoder.encode(cam))); 206 | byte[] encoded = UperEncoder.encode(cam); 207 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 208 | assertEquals("01020000000000644006B49D272D693A41BFFFFFFC23B7743E40E11FDFFFFEBFE9ED0737530F5FFFB09000013FFFFFFFFF1CE3FFFFFFFFF1CE00", 209 | UperEncoder.hexStringFromBytes(encoded)); 210 | } 211 | 212 | @Test public void test5() throws IllegalArgumentException, IllegalAccessException { 213 | CoopIts.Cam cam = 214 | new CoopIts.Cam( 215 | new ItsPduHeader(new MessageId(MessageId.cam)), 216 | new CoopAwareness( 217 | new CoopIts.GenerationDeltaTime(100), 218 | new CamParameters( 219 | new BasicContainer( 220 | new StationType(CoopIts.StationType.unknown), 221 | new ReferencePosition( 222 | new Latitude(57), 223 | new Longitude(13), 224 | new PosConfidenceEllipse( 225 | new SemiAxisLength(SemiAxisLength.unavailable), 226 | new SemiAxisLength(), 227 | new HeadingValue(HeadingValue.unavailable)), 228 | new Altitude( 229 | new AltitudeValue(AltitudeValue.unavailable), 230 | AltitudeConfidence.unavailable))), 231 | new HighFrequencyContainer( 232 | BasicVehicleContainerHighFrequency.builder() 233 | .accelerationControl(AccelerationControl.builder() 234 | .accEngaged(true) 235 | .gasPedalEngaged(true) 236 | .create()) 237 | .create()), 238 | new LowFrequencyContainer( 239 | new BasicVehicleContainerLowFrequency( 240 | VehicleRole.default_, 241 | ExteriorLights.builder().create(), 242 | new PathHistory( 243 | new PathPoint(), 244 | new PathPoint()))), 245 | new SpecialVehicleContainer( 246 | new PublicTransportContainer( 247 | true, 248 | new PtActivation( 249 | new PtActivationType(PtActivationType.undefinedCodingType), 250 | new PtActivationData( 251 | (byte) 0x0a, 252 | (byte) 0xff))))))); 253 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(UperEncoder.encode(cam))); 254 | byte[] encoded = UperEncoder.encode(cam); 255 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 256 | assertEquals("01020000000000646006B49D272D693A41BFFFFFFC23B7743E40E11FDFFFFEBFE9ED0737530F5FFFB09000013FFFFFFFFF1CE3FFFFFFFFF1CE060010AFF0", 257 | UperEncoder.hexStringFromBytes(encoded)); 258 | } 259 | 260 | @Test public void test6() throws IllegalArgumentException, IllegalAccessException { 261 | CoopIts.Cam cam = 262 | new CoopIts.Cam( 263 | new ItsPduHeader(new MessageId(MessageId.cam)), 264 | new CoopAwareness( 265 | new CoopIts.GenerationDeltaTime(100), 266 | new CamParameters( 267 | new BasicContainer( 268 | new StationType(CoopIts.StationType.unknown), 269 | new ReferencePosition( 270 | new Latitude(57), 271 | new Longitude(13), 272 | new PosConfidenceEllipse( 273 | new SemiAxisLength(SemiAxisLength.unavailable), 274 | new SemiAxisLength(), 275 | new HeadingValue(HeadingValue.unavailable)), 276 | new Altitude( 277 | new AltitudeValue(AltitudeValue.unavailable), 278 | AltitudeConfidence.unavailable))), 279 | new HighFrequencyContainer( 280 | BasicVehicleContainerHighFrequency.builder() 281 | .accelerationControl(AccelerationControl.builder() 282 | .accEngaged(true) 283 | .gasPedalEngaged(true) 284 | .create()) 285 | .create()), 286 | new LowFrequencyContainer( 287 | new BasicVehicleContainerLowFrequency( 288 | VehicleRole.default_, 289 | ExteriorLights.builder().create(), 290 | new PathHistory( 291 | new PathPoint(), 292 | new PathPoint()))), 293 | new SpecialVehicleContainer( 294 | new RoadWorksContainerBasic( 295 | null, 296 | new LightBarSirenInUse(), 297 | new ClosedLanes( 298 | DrivingLaneStatus.builder() 299 | .setBit(3, true) 300 | .setBit(5, true) 301 | .outermostLaneClosed(true) 302 | .create() 303 | )))))); 304 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(UperEncoder.encode(cam))); 305 | byte[] encoded = UperEncoder.encode(cam); 306 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 307 | assertEquals("01020000000000646006B49D272D693A41BFFFFFFC23B7743E40E11FDFFFFEBFE9ED0737530F5FFFB09000013FFFFFFFFF1CE3FFFFFFFFF1CE1A0AA8", 308 | UperEncoder.hexStringFromBytes(encoded)); 309 | 310 | Object decoded = UperEncoder.decode(encoded, cam.getClass()); 311 | byte[] reencoded = UperEncoder.encode(decoded); 312 | assertArrayEquals("encoded and reencoded", encoded, reencoded); 313 | } 314 | 315 | @Test public void basicDenmTest() throws IllegalArgumentException, IllegalAccessException { 316 | CoopIts.Denm denm = new CoopIts.Denm(); 317 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(UperEncoder.encode(denm))); 318 | byte[] encoded = UperEncoder.encode(denm); 319 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 320 | assertEquals("010100000000010000000000000000000000000000000006B49D201D693A401FFFFFFE11DBBA1F012C0000", 321 | UperEncoder.hexStringFromBytes(encoded)); 322 | } 323 | 324 | @Test public void sequenceOfSizeExtensionTest() throws IllegalArgumentException, IllegalAccessException { 325 | CoopIts.Denm denm = new CoopIts.Denm( 326 | new ItsPduHeader(new MessageId(MessageId.denm)), 327 | new DecentralizedEnvironmentalNotificationMessage( 328 | new ManagementContainer(), 329 | null, 330 | null, 331 | new AlacarteContainer( 332 | null, 333 | null, 334 | null, 335 | new RoadWorksContainerExtended( 336 | null, 337 | null, 338 | new RestrictedTypes( 339 | new StationType(StationType.cyclist), 340 | new StationType(StationType.cyclist) 341 | ), 342 | null, 343 | null, 344 | null, 345 | null, 346 | null, 347 | null 348 | ), 349 | null, 350 | null 351 | ) 352 | ) 353 | ); 354 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(UperEncoder.encode(denm))); 355 | byte[] encoded = UperEncoder.encode(denm); 356 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 357 | assertEquals("010100000000210000000000000000000000000000000006B49D201D693A401FFFFFFE11DBBA1F012C000420102020", 358 | UperEncoder.hexStringFromBytes(encoded)); 359 | 360 | Object decoded = UperEncoder.decode(encoded, denm.getClass()); 361 | byte[] reencoded = UperEncoder.encode(decoded); 362 | assertArrayEquals("encoded and reencoded", encoded, reencoded); 363 | } 364 | 365 | 366 | @Test public void sequenceOfSizeExtensionTest2() throws IllegalArgumentException, IllegalAccessException { 367 | CoopIts.Denm denm = new CoopIts.Denm( 368 | new ItsPduHeader(new MessageId(MessageId.denm)), 369 | new DecentralizedEnvironmentalNotificationMessage( 370 | new ManagementContainer(), 371 | null, 372 | null, 373 | new AlacarteContainer( 374 | null, 375 | null, 376 | null, 377 | new RoadWorksContainerExtended( 378 | null, 379 | null, 380 | new RestrictedTypes( 381 | new StationType(StationType.bus) 382 | ), 383 | null, 384 | null, 385 | null, 386 | null, 387 | null, 388 | null 389 | ), 390 | null, 391 | null 392 | ) 393 | ) 394 | ); 395 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(UperEncoder.encode(denm))); 396 | byte[] encoded = UperEncoder.encode(denm); 397 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 398 | assertEquals("010100000000210000000000000000000000000000000006B49D201D693A401FFFFFFE11DBBA1F012C0004200060", 399 | UperEncoder.hexStringFromBytes(encoded)); 400 | 401 | Object decoded = UperEncoder.decode(encoded, denm.getClass()); 402 | byte[] reencoded = UperEncoder.encode(decoded); 403 | assertArrayEquals("encoded and reencoded", encoded, reencoded); 404 | } 405 | 406 | @Test public void DenmTestLong() throws IllegalArgumentException, IllegalAccessException { 407 | CoopIts.Denm denm = new CoopIts.Denm( 408 | new ItsPduHeader(new MessageId(MessageId.denm)), 409 | new DecentralizedEnvironmentalNotificationMessage( 410 | new ManagementContainer( 411 | new ActionID( 412 | new StationID(82), 413 | new SequenceNumber(3879) 414 | ), 415 | new TimestampIts(298379), 416 | new TimestampIts(4879437), 417 | Termination.defaultValue(), 418 | new ReferencePosition(), 419 | RelevanceDistance.defaultValue(), 420 | RelevanceTrafficDirection.defaultValue(), 421 | new ValidityDuration(83209), 422 | new TransmissionInterval(232), 423 | new StationType(8) 424 | ), 425 | new SituationContainer( 426 | new InformationQuality(3), 427 | new CauseCode( 428 | new CauseCodeType(CauseCodeType.adverseWeatherCondition_Visibility), 429 | new SubCauseCodeType(13) 430 | ), 431 | new CauseCode( 432 | new CauseCodeType(67), 433 | new SubCauseCodeType(95) 434 | ), 435 | new EventHistory( 436 | new EventPoint( 437 | new DeltaReferencePosition(), 438 | new PathDeltaTime(837), 439 | new InformationQuality(6) 440 | ) 441 | ) 442 | ), 443 | new LocationContainer( 444 | new Speed( 445 | new SpeedValue(950), 446 | new SpeedConfidence(100) 447 | ), 448 | new Heading( 449 | new HeadingValue(1800), 450 | new HeadingConfidence(37) 451 | ), 452 | new Traces( 453 | new PathHistory( 454 | new PathPoint( 455 | new DeltaReferencePosition( 456 | new DeltaLatitude(28389), 457 | new DeltaLongitude(83487), 458 | new DeltaAltitude(-5000)), 459 | new PathDeltaTime(200) 460 | ), 461 | new PathPoint() 462 | ), 463 | new PathHistory( 464 | new PathPoint() 465 | ) 466 | ), 467 | RoadType.defaultValue() 468 | ), 469 | new AlacarteContainer( 470 | new LanePosition(LanePosition.secondLaneFromOutside), 471 | new ImpactReductionContainer( 472 | new HeightLonCarr(), 473 | new HeightLonCarr(), 474 | new PosLonCarr(), 475 | new PosLonCarr(), 476 | new PositionOfPillars( 477 | new PosPillar()), 478 | new PosCentMass(), 479 | new WheelBaseVehicle(), 480 | new TurningRadius(), 481 | new PosFrontAx(), 482 | new PositionOfOccupants(), 483 | new VehicleMass(), 484 | RequestResponseIndication.defaultValue() 485 | ), 486 | new Temperature(27), 487 | new RoadWorksContainerExtended( 488 | new LightBarSirenInUse(), 489 | new ClosedLanes( 490 | HardShoulderStatus.availableForDriving, 491 | new DrivingLaneStatus(true, false, false, true)), 492 | new RestrictedTypes( 493 | new StationType(StationType.bus) 494 | ), 495 | new SpeedLimit(120 * SpeedLimit.oneKmPerHour), 496 | new CauseCode( 497 | new CauseCodeType(CauseCodeType.adverseWeatherCondition_Visibility), 498 | new SubCauseCodeType(13) 499 | ), 500 | new ItineraryPath( 501 | new ReferencePosition() 502 | ), 503 | new DeltaReferencePosition(), 504 | TrafficRule.noPassingForTrucks, 505 | new ReferenceDenms( 506 | new ActionID()) 507 | ), 508 | PositioningSolutionType.sGNSSplusDR, 509 | new StationaryVehicleContainer( 510 | StationarySince.lessThan15Minutes, 511 | null, 512 | null, 513 | new NumberOfOccupants(13), 514 | null, 515 | new EnergyStorageType() 516 | ) 517 | ) 518 | ) 519 | ); 520 | // logger.debug("data hex: {}", UperEncoder.toHexString(UperEncoder.boolToBits(UperEncoder.encodeAsList(denm)))); 521 | byte[] encoded = UperEncoder.encode(denm); 522 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 523 | assertEquals("010100000000EF80000029079380000091B160000253A26B5A4E900EB49D200FFFFFFF08EDDD0F828A120738436241A86BE0FFFFFFFFFE39C01A2670EDB1B84242166EE4D1878F0A0031DFFFFFFFFF8E7017FFFFFFFFE39C1F9E3C7FBF0EFDFBFA600001FFABFFC63900CEE241A06B49D201D693A401FFFFFFE11DBBA1FFFFFFFFFFC73840000000000000E58680", 524 | UperEncoder.hexStringFromBytes(encoded)); 525 | 526 | Object decoded = UperEncoder.decode(encoded, denm.getClass()); 527 | byte[] reencoded = UperEncoder.encode(decoded); 528 | assertArrayEquals("encoded and reencoded", encoded, reencoded); 529 | } 530 | 531 | @Test public void DenmTestString() throws IllegalArgumentException, IllegalAccessException { 532 | CoopIts.Denm denm = new CoopIts.Denm( 533 | new ItsPduHeader(new MessageId(MessageId.denm)), 534 | new DecentralizedEnvironmentalNotificationMessage( 535 | new ManagementContainer( 536 | new ActionID( 537 | new StationID(82), 538 | new SequenceNumber(3879) 539 | ), 540 | new TimestampIts(298379), 541 | new TimestampIts(4879437), 542 | Termination.defaultValue(), 543 | new ReferencePosition(), 544 | RelevanceDistance.defaultValue(), 545 | RelevanceTrafficDirection.defaultValue(), 546 | new ValidityDuration(83209), 547 | new TransmissionInterval(232), 548 | new StationType(8) 549 | ), 550 | new SituationContainer( 551 | new InformationQuality(3), 552 | new CauseCode( 553 | new CauseCodeType(CauseCodeType.adverseWeatherCondition_Visibility), 554 | new SubCauseCodeType(13) 555 | ), 556 | new CauseCode( 557 | new CauseCodeType(67), 558 | new SubCauseCodeType(95) 559 | ), 560 | new EventHistory( 561 | new EventPoint( 562 | new DeltaReferencePosition(), 563 | new PathDeltaTime(837), 564 | new InformationQuality(6) 565 | ) 566 | ) 567 | ), 568 | new LocationContainer( 569 | new Speed( 570 | new SpeedValue(950), 571 | new SpeedConfidence(100) 572 | ), 573 | new Heading( 574 | new HeadingValue(1800), 575 | new HeadingConfidence(37) 576 | ), 577 | new Traces( 578 | new PathHistory( 579 | new PathPoint( 580 | new DeltaReferencePosition( 581 | new DeltaLatitude(28389), 582 | new DeltaLongitude(83487), 583 | new DeltaAltitude(-5000)), 584 | new PathDeltaTime(200) 585 | ), 586 | new PathPoint() 587 | ), 588 | new PathHistory( 589 | new PathPoint() 590 | ) 591 | ), 592 | RoadType.defaultValue() 593 | ), 594 | new AlacarteContainer( 595 | new LanePosition(LanePosition.secondLaneFromOutside), 596 | new ImpactReductionContainer( 597 | new HeightLonCarr(), 598 | new HeightLonCarr(), 599 | new PosLonCarr(), 600 | new PosLonCarr(), 601 | new PositionOfPillars( 602 | new PosPillar()), 603 | new PosCentMass(), 604 | new WheelBaseVehicle(), 605 | new TurningRadius(), 606 | new PosFrontAx(), 607 | new PositionOfOccupants(), 608 | new VehicleMass(), 609 | RequestResponseIndication.defaultValue() 610 | ), 611 | new Temperature(27), 612 | new RoadWorksContainerExtended( 613 | new LightBarSirenInUse(), 614 | new ClosedLanes( 615 | HardShoulderStatus.availableForDriving, 616 | new DrivingLaneStatus(true, false, false, true)), 617 | new RestrictedTypes( 618 | new StationType(StationType.bus) 619 | ), 620 | new SpeedLimit(120 * SpeedLimit.oneKmPerHour), 621 | new CauseCode( 622 | new CauseCodeType(CauseCodeType.adverseWeatherCondition_Visibility), 623 | new SubCauseCodeType(13) 624 | ), 625 | new ItineraryPath( 626 | new ReferencePosition() 627 | ), 628 | new DeltaReferencePosition(), 629 | TrafficRule.noPassingForTrucks, 630 | new ReferenceDenms( 631 | new ActionID()) 632 | ), 633 | PositioningSolutionType.sGNSSplusDR, 634 | new StationaryVehicleContainer( 635 | StationarySince.lessThan15Minutes, 636 | null, 637 | null, 638 | new NumberOfOccupants(13), 639 | new VehicleIdentification( 640 | new WMInumber("asd"), 641 | new VDS("zxcABC") 642 | ), 643 | new EnergyStorageType() 644 | ) 645 | ) 646 | ) 647 | ); 648 | // logger.debug("data hex: {}", UperEncoder.toHexString(UperEncoder.boolToBits(UperEncoder.encodeAsList(denm)))); 649 | byte[] encoded = UperEncoder.encode(denm); 650 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 651 | assertEquals("010100000000EF80000029079380000091B160000253A26B5A4E900EB49D200FFFFFFF08EDDD0F828A120738436241A86BE0FFFFFFFFFE39C01A2670EDB1B84242166EE4D1878F0A0031DFFFFFFFFF8E7017FFFFFFFFE39C1F9E3C7FBF0EFDFBFA600001FFABFFC63900CEE241A06B49D201D693A401FFFFFFE11DBBA1FFFFFFFFFFC73840000000000000E786BB0F3C9EBC63830A1800", 652 | UperEncoder.hexStringFromBytes(encoded)); 653 | 654 | Object decoded = UperEncoder.decode(encoded, denm.getClass()); 655 | byte[] reencoded = UperEncoder.encode(decoded); 656 | assertArrayEquals("encoded and reencoded", encoded, reencoded); 657 | } 658 | 659 | @Test public void StringTest() throws IllegalArgumentException, IllegalAccessException { 660 | Object pdu = new VehicleIdentification( 661 | new WMInumber("asd"), 662 | new VDS("zxcABC") 663 | ); 664 | byte[] encoded = UperEncoder.encode(pdu); 665 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 666 | assertEquals("761E793D78C7061430", 667 | UperEncoder.hexStringFromBytes(encoded)); 668 | } 669 | 670 | @Test public void Utf8StringTest() throws IllegalArgumentException, IllegalAccessException { 671 | Object pdu = new DangerousGoodsExtended( 672 | DangerousGoodsBasic.explosives4, 13, false, false, true, "abc", "cde", "zxc" 673 | ); 674 | byte[] encoded = UperEncoder.encode(pdu); 675 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 676 | assertEquals("E300348B0E2C62C793281BD3C318", 677 | UperEncoder.hexStringFromBytes(encoded)); 678 | } 679 | 680 | @Test public void Utf8StringTest2() throws IllegalArgumentException, IllegalAccessException { 681 | Object pdu = new DangerousGoodsExtended( 682 | DangerousGoodsBasic.explosives4, 13, false, false, true, "abc", "cde", "a" 683 | ); 684 | byte[] encoded = UperEncoder.encode(pdu); 685 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 686 | assertEquals("E300348B0E2C62C793280B08", 687 | UperEncoder.hexStringFromBytes(encoded)); 688 | } 689 | 690 | @Test public void Utf8StringTest3() throws IllegalArgumentException, IllegalAccessException { 691 | Object pdu = new DangerousGoodsExtended( 692 | DangerousGoodsBasic.explosives4, 13, false, false, true, "abc", "cde", "abcöxyz" 693 | ); 694 | byte[] encoded = UperEncoder.encode(pdu); 695 | logger.debug("data hex: {}", UperEncoder.hexStringFromBytes(encoded)); 696 | assertEquals("E300348B0E2C62C79328430B131E1DB3C3CBD0", 697 | UperEncoder.hexStringFromBytes(encoded)); 698 | } 699 | 700 | @Test public void testFail() throws IllegalArgumentException, IllegalAccessException { 701 | //fail("not implemented yet"); 702 | } 703 | 704 | @Test public void testException() { 705 | 706 | CoopIts.Cam cam = 707 | new CoopIts.Cam( 708 | new ItsPduHeader(new MessageId(MessageId.cam)), 709 | new CoopAwareness( 710 | new CoopIts.GenerationDeltaTime(100), 711 | new CamParameters( 712 | new BasicContainer( 713 | new StationType(CoopIts.StationType.unknown), 714 | new ReferencePosition( 715 | new Latitude(900000001 + 1), 716 | new Longitude(13), 717 | new PosConfidenceEllipse( 718 | new SemiAxisLength(SemiAxisLength.unavailable), 719 | new SemiAxisLength(), 720 | new HeadingValue(HeadingValue.unavailable)), 721 | new Altitude( 722 | new AltitudeValue(AltitudeValue.unavailable), 723 | AltitudeConfidence.unavailable))), 724 | new HighFrequencyContainer( 725 | BasicVehicleContainerHighFrequency.builder() 726 | .accelerationControl(AccelerationControl.builder() 727 | .accEngaged(true) 728 | .gasPedalEngaged(true) 729 | .create()) 730 | .create())))); 731 | 732 | try { 733 | byte[] encoded2 = UperEncoder.encode(cam); 734 | } catch (IllegalArgumentException e) { 735 | logger.debug("got expected exception {}", e.getMessage()); 736 | return; 737 | } 738 | fail("no exception"); 739 | } 740 | 741 | } 742 | --------------------------------------------------------------------------------