diff --git a/.circleci/config.yml b/.circleci/config.yml index 75b665fd5..ca7e2700a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -189,6 +189,49 @@ jobs: command: | echo "$DOCKERHUB_PASSWORD" | docker login --username $DOCKERHUB_USERNAME --password-stdin docker push usdotfhwaops/v2xhubarm:latest + port_drayage_webservice_build_develop : + docker: + - image: cimg/openjdk:11.0.12 + # Set working directory + working_directory: "/home/V2X-Hub" + steps: + - setup_remote_docker + - checkout + - run: + name: Maven Build JAR + # Build Port Drayage Web Service + command: | + cd tools/port-drayage-webservice/ + mvn clean install + - run: + name: Build Docker Image and Push + # Build and push Port Drayage Web Service Docker images + command: | + cd tools/port-drayage-webservice/ + docker build -t usdotfhwaops/port-drayage-webservice:latest . + echo "$DOCKERHUB_PASSWORD" | docker login --username $DOCKERHUB_USERNAME --password-stdin + docker push usdotfhwaops/port-drayage-webservice:latest + port_drayage_webservice_build : + docker: + - image: cimg/openjdk:11.0.12 + # Set working directory + steps: + - setup_remote_docker + - checkout + - run: + name: Maven Build JAR + # Build Port Drayage Web Service + command: | + cd tools/port-drayage-webservice/ + mvn clean install + - run: + name: Build Docker Image and Push + # Build and push Port Drayage Web Service Docker images + command: | + cd tools/port-drayage-webservice/ + docker build -t usdotfhwaops/port-drayage-webservice:${CIRCLE_BRANCH,,} . + echo "$DOCKERHUB_PASSWORD" | docker login --username $DOCKERHUB_USERNAME --password-stdin + docker push usdotfhwaops/port-drayage-webservice:${CIRCLE_BRANCH,,} workflows: version: 2 build: @@ -215,5 +258,13 @@ workflows: - sonar-scanner_develop: requires: - docker_build_push_develop + - port_drayage_webservice_build_develop: + filters: + branches: + only: develop + - port_drayage_webservice_build: + filters: + branches: + ignore: develop diff --git a/.gitignore b/.gitignore index 25637dab5..98390dbb5 100644 --- a/.gitignore +++ b/.gitignore @@ -78,3 +78,9 @@ Thumbs.db #docker-compose variables .env + +#Maven build directory +tools/port-drayage-webservice/target/ + +#Java PKS for HTTPS setup +tools/port-drayage-webservice/src/main/resources/tutorial.jks diff --git a/.sonarqube/sonar-scanner.properties b/.sonarqube/sonar-scanner.properties index 334ba3ebb..9bbb4a3ab 100644 --- a/.sonarqube/sonar-scanner.properties +++ b/.sonarqube/sonar-scanner.properties @@ -47,7 +47,7 @@ sonar.modules= PedestrianPlugin, \ TmxTools, \ MessageLoggerPlugin, \ CommandPlugin, \ - MobilityOperationPlugin, \ + PortDrayagePlugin, \ ODELoggerPlugin, \ DsrcImmediateForwardPlugin, \ MessageReceiverPlugin @@ -61,7 +61,7 @@ TmxUtils.sonar.projectBaseDir =/home/V2X-Hub/src/tmx/TmxUtils CARMACloudPlugin.sonar.projectBaseDir =/home/V2X-Hub/src/v2i-hub/CARMACloudPlugin CommandPlugin.sonar.projectBaseDir =/home/V2X-Hub/src/v2i-hub/CommandPlugin CswPlugin.sonar.projectBaseDir =/home/V2X-Hub/src/v2i-hub/CswPlugin -MobilityOperationPlugin.sonar.projectBaseDir =/home/V2X-Hub/src/v2i-hub/MobilityOperationPlugin +PortDrayagePlugin.sonar.projectBaseDir =/home/V2X-Hub/src/v2i-hub/PortDrayagePlugin ODELoggerPlugin.sonar.projectBaseDir =/home/V2X-Hub/src/v2i-hub/ODELoggerPlugin MessageLoggerPlugin.sonar.projectBaseDir =/home/V2X-Hub/src/v2i-hub/MessageLoggerPlugin DmsPlugin.sonar.projectBaseDir =/home/V2X-Hub/src/v2i-hub/DmsPlugin @@ -85,6 +85,7 @@ TmxTools.sonar.sources =src TmxUtils.sonar.sources =src MessageLoggerPlugin.sonar.sources =src CswPlugin.sonar.sources =src +PortDrayagePlugin.sonar.sources =src DmsPlugin.sonar.sources =src DsrcImmediateForwardPlugin.sonar.sources =src LocationPlugin.sonar.sources =src @@ -113,6 +114,7 @@ MobilityOperationPlugin.sonar.sources =src TmxUtils.sonar.cfamily.gcov.reportsPath =coverage #MessageLoggerPlugin.sonar.cfamily.gcov.reportsPath =coverage #CswPlugin.sonar.cfamily.gcov.reportsPath =coverage +#PortDrayagePlugin.sonar.cfamily.gcov.reportsPath =coverage #DmsPlugin.sonar.cfamily.gcov.reportsPath =coverage #DsrcImmediateForwardPlugin.sonar.cfamily.gcov.reportsPath =coverage #LocationPlugin.sonar.cfamily.gcov.reportsPath =coverage @@ -138,6 +140,7 @@ TmxUtils.sonar.tests=test #TmxTools.sonar.tests=test #MessageLoggerPlugin.sonar.tests=test #CswPlugin.sonar.tests=test +#PortDrayagePlugin.sonar.tests=test #DmsPlugin.sonar.tests=test #DsrcImmediateForwardPlugin.sonar.tests=test #LocationPlugin.sonar.tests=test diff --git a/Dockerfile b/Dockerfile index 0085b6fb2..e483c6e53 100644 --- a/Dockerfile +++ b/Dockerfile @@ -60,6 +60,11 @@ RUN make install WORKDIR /home/V2X-Hub/ext/ccserver RUN cmake . RUN make +RUN make install + +WORKDIR /home/V2X-Hub/ext/pdclient +RUN cmake . +RUN make RUN make install ### setup and install v2x-hub core and plugins @@ -101,8 +106,8 @@ RUN ln -s ../bin TimPlugin/bin RUN zip TimPlugin.zip TimPlugin/bin/TimPlugin TimPlugin/manifest.json RUN ln -s ../bin CARMACloudPlugin/bin RUN zip CARMACloudPlugin.zip CARMACloudPlugin/bin/CARMACloudPlugin CARMACloudPlugin/manifest.json -RUN ln -s ../bin MobilityOperationPlugin/bin -RUN zip MobilityOperationPlugin.zip MobilityOperationPlugin/bin/MobilityOperationPlugin MobilityOperationPlugin/manifest.json +RUN ln -s ../bin PortDrayagePlugin/bin +RUN zip PortDrayagePlugin.zip PortDrayagePlugin/bin/PortDrayagePlugin PortDrayagePlugin/manifest.json RUN ln -s ../bin ODELoggerPlugin/bin RUN zip ODELoggerPlugin.zip ODELoggerPlugin/bin/ODELoggerPlugin ODELoggerPlugin/manifest.json diff --git a/configuration/amd64/docker-compose.yml b/configuration/amd64/docker-compose.yml index da7f207f3..8bdd188e0 100755 --- a/configuration/amd64/docker-compose.yml +++ b/configuration/amd64/docker-compose.yml @@ -16,9 +16,10 @@ services: - mysql_root_password volumes: - ./mysql/localhost.sql:/docker-entrypoint-initdb.d/localhost.sql + - ./mysql/port_drayage.sql:/docker-entrypoint-initdb.d/port_drayage.sql php: - image: usdotfhwaops/php:latest + image: usdotfhwaops/php:6.2 container_name: php network_mode: host depends_on: @@ -27,7 +28,7 @@ services: tty: true v2xhub: - image: usdotfhwaops/v2xhubamd:latest + image: usdotfhwaops/v2xhubamd:6.2 container_name: v2xhub network_mode: host restart: always @@ -40,6 +41,10 @@ services: volumes: - ./logs:/var/log/tmx - ./MAP:/var/www/plugins/MAP + port_drayage_webservice: + image: usdotfhwaops/port-drayage-webservice:6.2 + container_name: port_drayage_webservice + network_mode: host secrets: mysql_password: file: ./secrets/mysql_password.txt diff --git a/configuration/amd64/mysql/localhost.sql b/configuration/amd64/mysql/localhost.sql index 0430a75cf..06d9abcf4 100644 --- a/configuration/amd64/mysql/localhost.sql +++ b/configuration/amd64/mysql/localhost.sql @@ -1,8 +1,8 @@ --- MySQL dump 10.13 Distrib 5.7.34, for Linux (x86_64) +-- MySQL dump 10.13 Distrib 5.7.35, for Linux (x86_64) -- --- Host: localhost Database: IVP +-- Host: 127.0.0.1 Database: IVP -- ------------------------------------------------------ --- Server version 5.7.34 +-- Server version 5.7.35 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -38,7 +38,7 @@ CREATE TABLE `eventLog` ( `logLevel` enum('Debug','Info','Warning','Error','Fatal') NOT NULL COMMENT 'The type of event being logged, one of - Debug - Info - Warn - Error', `uploaded` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='This table records events generated by every IVP core component and plugin in the IVP platform. '; +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1 COMMENT='This table records events generated by every IVP core component and plugin in the IVP platform. '; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -78,7 +78,7 @@ CREATE TABLE `installedPlugin` ( LOCK TABLES `installedPlugin` WRITE; /*!40000 ALTER TABLE `installedPlugin` DISABLE KEYS */; -INSERT INTO `installedPlugin` VALUES (1,1,'/var/www/plugins/CommandPlugin','/bin/CommandPlugin','manifest.json','',0,500000),(2,2,'/var/www/plugins/CswPlugin','/bin/CswPlugin','manifest.json','',0,500000),(3,3,'/var/www/plugins/DmsPlugin','/bin/DmsPlugin','manifest.json','',0,500000),(4,4,'/var/www/plugins/DsrcImmediateForwardPlugin','/bin/DsrcImmediateForwardPlugin','manifest.json','',0,500000),(5,5,'/var/www/plugins/LocationPlugin','/bin/LocationPlugin','manifest.json','',0,500000),(6,6,'/var/www/plugins/MapPlugin','/bin/MapPlugin','manifest.json','',0,500000),(7,7,'/var/www/plugins/MessageReceiverPlugin','/bin/MessageReceiverPlugin','manifest.json','',0,500000),(8,8,'/var/www/plugins/ODEPlugin','/bin/ODEPlugin','manifest.json','',0,500000),(9,9,'/var/www/plugins/RtcmPlugin','/bin/RtcmPlugin','manifest.json','',0,500000),(10,10,'/var/www/plugins/SpatPlugin','/bin/SpatPlugin','manifest.json','',0,500000),(11,11,'/var/www/plugins/PreemptionPlugin','/bin/PreemptionPlugin','manifest.json','',0,500000),(12,12,'/var/www/plugins/SPaTLoggerPlugin','/bin/SPaTLoggerPlugin','manifest.json','',0,500000),(13,13,'/var/www/plugins/MessageLoggerPlugin','/bin/MessageLoggerPlugin','manifest.json','',0,500000),(14,14,'/var/www/plugins/PedestrianPlugin','/bin/PedestrianPlugin','manifest.json','',0,500000),(15,15,'/var/www/plugins/TimPlugin','/bin/TimPlugin','manifest.json','',0,500000),(16,16,'/var/www/plugins/CARMACloudPlugin','/bin/CARMACloudPlugin','manifest.json','',0,500000),(17,17,'/var/www/plugins/MobilityOperationPlugin','/bin/MobilityOperationPlugin','manifest.json','',0,500000),(18,18,'/var/www/plugins/ODELoggerPlugin','/bin/ODELoggerPlugin','manifest.json','',0,500000); +INSERT INTO `installedPlugin` VALUES (1,1,'/var/www/plugins/CommandPlugin','/bin/CommandPlugin','manifest.json','',1,500000),(2,2,'/var/www/plugins/CswPlugin','/bin/CswPlugin','manifest.json','',0,500000),(3,3,'/var/www/plugins/DmsPlugin','/bin/DmsPlugin','manifest.json','',0,500000),(4,4,'/var/www/plugins/DsrcImmediateForwardPlugin','/bin/DsrcImmediateForwardPlugin','manifest.json','',0,500000),(5,5,'/var/www/plugins/LocationPlugin','/bin/LocationPlugin','manifest.json','',0,500000),(6,6,'/var/www/plugins/MapPlugin','/bin/MapPlugin','manifest.json','',0,500000),(7,7,'/var/www/plugins/MessageReceiverPlugin','/bin/MessageReceiverPlugin','manifest.json','',0,500000),(8,8,'/var/www/plugins/ODEPlugin','/bin/ODEPlugin','manifest.json','',0,500000),(9,9,'/var/www/plugins/RtcmPlugin','/bin/RtcmPlugin','manifest.json','',0,500000),(10,10,'/var/www/plugins/SpatPlugin','/bin/SpatPlugin','manifest.json','',0,500000),(11,11,'/var/www/plugins/PreemptionPlugin','/bin/PreemptionPlugin','manifest.json','',0,500000),(12,12,'/var/www/plugins/SPaTLoggerPlugin','/bin/SPaTLoggerPlugin','manifest.json','',0,500000),(13,13,'/var/www/plugins/MessageLoggerPlugin','/bin/MessageLoggerPlugin','manifest.json','',0,500000),(14,14,'/var/www/plugins/PedestrianPlugin','/bin/PedestrianPlugin','manifest.json','',0,500000),(15,15,'/var/www/plugins/TimPlugin','/bin/TimPlugin','manifest.json','',0,500000),(16,16,'/var/www/plugins/CARMACloudPlugin','/bin/CARMACloudPlugin','manifest.json','',0,500000),(17,17,'/var/www/plugins/PortDrayagePlugin','/bin/PortDrayagePlugin','manifest.json','',0,500000),(18,18,'/var/www/plugins/ODELoggerPlugin','/bin/ODELoggerPlugin','manifest.json','',0,500000); /*!40000 ALTER TABLE `installedPlugin` ENABLE KEYS */; UNLOCK TABLES; @@ -102,7 +102,7 @@ CREATE TABLE `messageActivity` ( KEY `pluginId` (`pluginId`), CONSTRAINT `messageActivity_ibfk_1` FOREIGN KEY (`messageTypeId`) REFERENCES `messageType` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `messageActivity_ibfk_2` FOREIGN KEY (`pluginId`) REFERENCES `plugin` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='This table records the most recent message activity of each active plugin in the IVP system. The data in this table is updated by the IVP plugin monitor core component for every message the plugin monitor receives.'; +) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=latin1 COMMENT='This table records the most recent message activity of each active plugin in the IVP system. The data in this table is updated by the IVP plugin monitor core component for every message the plugin monitor receives.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -155,7 +155,7 @@ CREATE TABLE `plugin` ( `version` text, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) -) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=latin1 COMMENT='This table lists the plugins loaded and available to run on the IVP platform.'; +) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=latin1 COMMENT='This table lists the plugins loaded and available to run on the IVP platform.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -164,7 +164,7 @@ CREATE TABLE `plugin` ( LOCK TABLES `plugin` WRITE; /*!40000 ALTER TABLE `plugin` DISABLE KEYS */; -INSERT INTO `plugin` VALUES (1,'CommandPlugin','Listens for websocket connections from the TMX admin portal and processes commands','5.0'),(2,'CSW','Provides Curve Speed Warning (CSW).','5.0'),(3,'DynamicMessageSign','Provides communication to a dynamic message sign.','5.0'),(4,'DSRCMessageManager','Plugin that listens for TMX messages and forwards them to the DSRC Radio (i.e. the RSU).','5.0'),(5,'Location','Plugin used to send out Location Messages using data from GPSD','5.0'),(6,'MAP','Plugin that reads intersection geometry from a configuration file and publishes a J2735 MAP message.','5.0'),(7,'MessageReceiver','Plugin to receive messages from an external DSRC radio or other source','5.0'),(8,'ODEPlugin','Plugin to forward messages to the Florida ODEPlugin network','5.0'),(9,'RTCM','Plugin to listen for RTCM messages from an NTRIP caster and route those messages over DSRC','5.0'),(10,'SPAT','Plugin that reads PTLM data from a configuration file, receives live data from the signal controller, and publishes a J2735 SPAT message.','5.0'),(11,'Preemption','Preemption plugin for the IVP system.','5.0'),(12,'SPaTLoggerPlugin','Listens for SPaT messages and logs them in a file in CSV format.','5.0'),(13,'MessageLoggerPlugin','Listens for J2735 messages and logs them in a file in JSON format.','5.0'),(14,'Pedestrian','Pedestrian plugin for the IVP system.','5.0'),(15,'TIM','Provides Traveller Information Message (TIM).','5.0'),(16,'CARMACloud','CARMA cloud plugin for making websocket connection with CARMA cloud .','5.0'),(17,'MobilityOperationPlugin','In development','5.0'),(18,'ODELoggerPlugin','Listens for J2735 messages and realtime forwards them to ODE.','5.0'); +INSERT INTO `plugin` VALUES (0,'Plugin System','The global configuration for all TMX plugins','4.0'),(1,'CommandPlugin','Listens for websocket connections from the TMX admin portal and processes commands','5.0'),(2,'CSW','Provides Curve Speed Warning (CSW).','5.0'),(3,'DynamicMessageSign','Provides communication to a dynamic message sign.','5.0'),(4,'DSRCMessageManager','Plugin that listens for TMX messages and forwards them to the DSRC Radio (i.e. the RSU).','5.0'),(5,'Location','Plugin used to send out Location Messages using data from GPSD','5.0'),(6,'MAP','Plugin that reads intersection geometry from a configuration file and publishes a J2735 MAP message.','5.0'),(7,'MessageReceiver','Plugin to receive messages from an external DSRC radio or other source','5.0'),(8,'ODEPlugin','Plugin to forward messages to the Florida ODEPlugin network','5.0'),(9,'RTCM','Plugin to listen for RTCM messages from an NTRIP caster and route those messages over DSRC','5.0'),(10,'SPAT','Plugin that reads PTLM data from a configuration file, receives live data from the signal controller, and publishes a J2735 SPAT message.','5.0'),(11,'Preemption','Preemption plugin for the IVP system.','5.0'),(12,'SPaTLoggerPlugin','Listens for SPaT messages and logs them in a file in CSV format.','5.0'),(13,'MessageLoggerPlugin','Listens for J2735 messages and logs them in a file in JSON format.','5.0'),(14,'Pedestrian','Pedestrian plugin for the IVP system.','5.0'),(15,'TIM','Provides Traveller Information Message (TIM).','5.0'),(16,'CARMACloud','CARMA cloud plugin for making websocket connection with CARMA cloud .','3.0.0'),(17,'PortDrayagePlugin','PortDrayagePlugin for sending freight trucks automated actions in a port.','5.0'),(18,'ODELoggerPlugin','Listens for J2735 messages and realtime forwards them to ODE.','5.0'),(19,'ivpcore.PluginMonitor','Core element that is responsible for starting/stopping installed plugins and monitoring the status of the plugins','3.2.0'),(20,'ivpcore.MessageProfiler','Core element that is responsible for profiling the statistics of received messages','3.2.0'),(21,'ivpcore.HistoryManager','Core element that is responsible for purging old log and history data','3.2.0'); /*!40000 ALTER TABLE `plugin` ENABLE KEYS */; UNLOCK TABLES; @@ -217,7 +217,7 @@ CREATE TABLE `pluginConfigurationParameter` ( UNIQUE KEY `pluginId_key` (`pluginId`,`key`), KEY `pluginId` (`pluginId`), CONSTRAINT `pluginConfigurationParameter_ibfk_1` FOREIGN KEY (`pluginId`) REFERENCES `plugin` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB AUTO_INCREMENT=95 DEFAULT CHARSET=latin1 COMMENT='This table lists the IVP system configuration parameters used by both core components and plugins to control the behavior of the system.'; +) ENGINE=InnoDB AUTO_INCREMENT=113 DEFAULT CHARSET=latin1 COMMENT='This table lists the IVP system configuration parameters used by both core components and plugins to control the behavior of the system.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -226,7 +226,7 @@ CREATE TABLE `pluginConfigurationParameter` ( LOCK TABLES `pluginConfigurationParameter` WRITE; /*!40000 ALTER TABLE `pluginConfigurationParameter` DISABLE KEYS */; -INSERT INTO `pluginConfigurationParameter` VALUES (1,1,'SleepMS','100','100','The length of milliseconds to sleep between processing all messages.'),(2,1,'SSLEnabled','true','true','Enable secure connection using SSL.'),(3,1,'SSLPath','/var/www/plugins/.ssl','/var/www/plugins/.ssl','The path to the directory containing the SSL key and certificate files.'),(4,1,'EventRowLimit','50','50','The maximum number of rows returned for the initial Event Log query.'),(5,1,'DownloadPath','/var/www/download','/var/www/download','The path to the directory where downloaded files will be saved.'),(6,1,'LogLevel','ERROR','ERROR','The log level for this plugin'),(7,2,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(8,2,'MapFile','IVP_GF_CSW.xml','IVP_GF_CSW.xml',''),(9,2,'Snap Interval','300','300','The interval in milliseconds to keep a vehicle within a zone before allowing it to transition out of all zones.'),(10,2,'Vehicle Timeout','2000','2000','Timeout in milliseconds when a vehicle is removed from all zones if a BSM has not been received.'),(11,3,'DMS IP Address','192.168.25.30','192.168.25.30','The IP address of the NTCIP Dynamic Message Sign.'),(12,3,'DMS Port','9090','9090','The port of the NTCIP Dynamic Message Sign.'),(13,3,'Enable DMS','True','True','If true all messages are sent to the Dynamic Message Sign using NTCIP 1203.'),(14,3,'Enable Sign Simulator','True','True','If true all messages are sent to the Sign Simulator using UDP.'),(15,3,'Force Message ID','-1','-1','Immediately activates the message ID specified, then resets back to -1.'),(16,3,'Message 01','','','The text to display on the sign for ID 01 with any formatting (see NTCIP 1203).'),(17,3,'Message 02','[jl3][pt15o0]25[np]MPH','[jl3][pt15o0]25[np]MPH','The text to display on the sign for ID 02 with any formatting (see NTCIP 1203).'),(18,3,'Message 03','[jl3][pt15o0]SLOW[np]DOWN','[jl3][pt15o0]SLOW[np]DOWN','The text to display on the sign for ID 03 with any formatting (see NTCIP 1203).'),(19,3,'Message 04','[jl3][pt15o0]CRVE[np]AHED','[jl3][pt15o0]CRVE[np]AHED','The text to display on the sign for ID 04 with any formatting (see NTCIP 1203).'),(20,3,'Sign Sim IP Address','192.168.25.31','192.168.25.31','The IP address of the Sign Simulator that is the receipient of UDP messages.'),(21,3,'Sign Sim Port','9090','9090','The UDP port of the Sign Simulator that is the receipient of UDP messages.'),(22,4,'Messages_Destination_1','{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"PSM\", \"SendType\": \"PSM\", \"PSID\": \"0x8002\" } ,{ \"TmxType\": \"TMSG07\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\" }] }','{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"PSM\", \"SendType\": \"PSM\", \"PSID\": \"0x8002\" } ,{ \"TmxType\": \"TMSG07\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\" }] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 1.'),(23,4,'Messages_Destination_2','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 2.'),(24,4,'Messages_Destination_3','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 3.'),(25,4,'Messages_Destination_4','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 4.'),(26,4,'Destination_1','127.0.0.1:1516','127.0.0.1:1516','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_1.'),(27,4,'Destination_2','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_2.'),(28,4,'Destination_3','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_3.'),(29,4,'Destination_4','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_4.'),(30,4,'Signature','False','False','True or False value indicating whether to sign the messages.'),(31,5,'Frequency','500','500','Rate to send Location Message in milliseconds'),(32,5,'LatchHeadingSpeed','2.5','2.5','Speed at which the heading parameter should be latched, in mph. Set to 0 to disable latching.'),(33,5,'GPSSource','localhost','localhost','Host where the GPSd is running'),(34,5,'SendRawNMEA','true','true','Route the raw NMEA strings from GPSd through TMX'),(35,6,'Frequency','1000','1000','The frequency to send the MAP message in milliseconds.'),(36,6,'MAP_Files','{ \"MapFiles\": [\n {\"Action\":0, \"FilePath\":\"GID_Telegraph-Twelve_Mile_withEgress.xml\"}\n] }','{ \"MapFiles\": [\n {\"Action\":0, \"FilePath\":\"GID_Telegraph-Twelve_Mile_withEgress.xml\"}\n] }','JSON data defining a list of map files. One map file for each action set specified by the TSC.'),(37,7,'IP','127.0.0.1','127.0.0.1','IP address for the incoming message network connection.'),(38,7,'Port','26789','26789','Port for the incoming message network connection.'),(39,7,'RouteDSRC','false','false','Set the flag to route a received J2735 message over DSRC.'),(40,7,'EnableSimulatedBSM','true','true','Accept and route incoming BSM messages from a V2I Hub simulator.'),(41,7,'EnableSimulatedSRM','true','true','Accept and route incoming SRM messages from a V2I Hub simulator.'),(42,7,'EnableSimulatedLocation','true','true','Accept and route incoming GPS location messages from a V2I Hub simulator.'),(43,8,'ODEIP','127.0.0.1','127.0.0.1','IP address for the ODE network connection.'),(44,8,'ODEPort','26789','26789','Port for the ODE network connection.'),(45,9,'Endpoint IP','156.63.133.118','156.63.133.118','NTRIP caster endpoint IP address'),(46,9,'Endpoint Port','2101','2101','NTRIP caster endpoint port'),(47,9,'Username','username','username','NTRIP caster authentication username'),(48,9,'Password','password','password','NTRIP caster authentication password'),(49,9,'Mountpoint','ODOT_RTCM23','ODOT_RTCM23','NTRIP caster mountpoint'),(50,9,'RTCM Version','Unknown','Unknown','Specify the expected RTCM message version (2.3 or 3.3) coming from the caster. Use Unknown to auto detect the version, which is done using trial and error, thus may be slow.'),(51,9,'Route RTCM','false','false','Route the RTCM messages created from NTRIP internally for use by other plugins.'),(52,10,'Intersection_Id','1','1','The intersection id for SPAT generated by this plugin.'),(53,10,'Intersection_Name','Intersection','Intersection','The intersection name for SPAT generated by this plugin.'),(54,10,'SignalGroupMapping','{\"SignalGroups\":[{\"SignalGroupId\":1,\"Phase\":1,\"Type\":\"vehicle\"},{\"SignalGroupId\":2,\"Phase\":2,\"Type\":\"vehicle\"},{\"SignalGroupId\":3,\"Phase\":3,\"Type\":\"vehicle\"},{\"SignalGroupId\":4,\"Phase\":4,\"Type\":\"vehicle\"},{\"SignalGroupId\":5,\"Phase\":5,\"Type\":\"vehicle\"},{\"SignalGroupId\":6,\"Phase\":6,\"Type\":\"vehicle\"},{\"SignalGroupId\":7,\"Phase\":7,\"Type\":\"vehicle\"},{\"SignalGroupId\":8,\"Phase\":8,\"Type\":\"vehicle\"},{\"SignalGroupId\":22,\"Phase\":2,\"Type\":\"pedestrian\"},{\"SignalGroupId\":24,\"Phase\":4,\"Type\":\"pedestrian\"},{\"SignalGroupId\":26,\"Phase\":6,\"Type\":\"pedestrian\"},{\"SignalGroupId\":28,\"Phase\":8,\"Type\":\"pedestrian\"}]}','{\"SignalGroups\":[{\"SignalGroupId\":1,\"Phase\":1,\"Type\":\"vehicle\"},{\"SignalGroupId\":2,\"Phase\":2,\"Type\":\"vehicle\"},{\"SignalGroupId\":3,\"Phase\":3,\"Type\":\"vehicle\"},{\"SignalGroupId\":4,\"Phase\":4,\"Type\":\"vehicle\"},{\"SignalGroupId\":5,\"Phase\":5,\"Type\":\"vehicle\"},{\"SignalGroupId\":6,\"Phase\":6,\"Type\":\"vehicle\"},{\"SignalGroupId\":7,\"Phase\":7,\"Type\":\"vehicle\"},{\"SignalGroupId\":8,\"Phase\":8,\"Type\":\"vehicle\"},{\"SignalGroupId\":22,\"Phase\":2,\"Type\":\"pedestrian\"},{\"SignalGroupId\":24,\"Phase\":4,\"Type\":\"pedestrian\"},{\"SignalGroupId\":26,\"Phase\":6,\"Type\":\"pedestrian\"},{\"SignalGroupId\":28,\"Phase\":8,\"Type\":\"pedestrian\"}]}','JSON data defining a list of SignalGroups and phases.'),(55,10,'Local_IP','','','The IPv4 address of the local computer for receiving Traffic Signal Controller Broadcast Messages.'),(56,10,'Local_UDP_Port','local port','local port','The local UDP port for reception of Traffic Signal Controller Broadcast Messages from the TSC.'),(57,10,'TSC_IP','','','The IPv4 address of the destination Traffic Signal Controller (TSC).'),(58,10,'TSC_Remote_SNMP_Port','','','The destination port on the Traffic Signal Controller (TSC) for SNMP NTCIP communication.'),(59,11,'Instance','0','0','The instance of Preemption plugin.'),(60,11,'BasePreemptionOid','.1.3.6.1.4.1.1206.4.2.1.6.3.1.2.','.1.3.6.1.4.1.1206.4.2.1.6.3.1.2.','The BasePreemptionOid of Preemption plugin.'),(61,11,'ipwithport',':',':','The ipwithport of Preemption plugin.'),(62,11,'snmp_community','public','public','The snmp_community of Preemption plugin.'),(63,11,'map_path','/geo.json','/geo.json','The map_path for Preemption plugin.'),(64,11,'allowedList','{\"validVehicles\":[\"292710445\",\"123456789\",\"2345678\"]}','{\"validVehicles\":[\"292710445\",\"123456789\",\"2345678\"]}','List of vehicles BSM id that are allowed'),(65,12,'File Size In MB','100','100','Maximum size of the SPaT log file in mb.'),(66,12,'Filename','spatTx','spatTx','Default name of the SPaT log file.'),(67,12,'File Location','/var/log/tmx','/var/log/tmx','The location where the log files are stored. DO NOT edit while using docker deployment of V2X-Hub!'),(68,13,'File Size In MB','100','100','Maximum size of the BSM log file in mb.'),(69,13,'Filename','bsmTx','bsmTx','Default name of the BSM log file.'),(70,13,'File Location','/var/log/tmx','/var/log/tmx','The location where the log files are stored. DO NOT edit while using docker deployment of V2X-Hub!'),(71,14,'Frequency','1000','1000','The frequency to send the PSM in milliseconds.'),(72,14,'Instance','0','0','The instance of Pedestrian plugin.'),(73,14,'WebServiceIP','127.0.0.1','127.0.0.1','IP address at which the web service exists'),(74,14,'WebServicePort','9000','9000','Port at which Web service exists'),(75,15,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(76,15,'MapFile','/var/www/plugins/MAP/IVP_GF_TIM.xml','/var/www/plugins/MAP/IVP_GF_TIM.xml',''),(77,15,'Start_Broadcast_Date','01-01-2019','01-01-2019','The Start Broadcast Date for the TIM message in the (mm-dd-YYYY) format.'),(78,15,'Stop_Broadcast_Date','12-31-2020','12-31-2020','The Stop Broadcast Date for the TIM message in the (mm-dd-YYYY) format.'),(79,15,'Start_Broadcast_Time','06:00:00','06:00:00','The Start Broadcast Time for the TIM message in the (HH:MM:SS) format.'),(80,15,'Stop_Broadcast_Time','21:00:00','21:00:00','The Start Broadcast Time for the TIM message in the (HH:MM:SS) format.'),(81,15,'WebServiceIP','127.0.0.1','127.0.0.1','IP address at which the web service exists'),(82,15,'WebServicePort','10000','10000','Port at which Web service exists'),(83,16,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(84,16,'Instance','0','0','The instance of this plugin.'),(85,16,'WebServiceIP','127.0.0.1','127.0.0.1','Server IP address for V2X hub'),(86,16,'WebServicePort','22222','22222','Server Port for V2X hub'),(87,17,'...','...','...','...'),(88,18,'instance','1','1','instance of the application'),(89,18,'schedule_frequency','1','1','sample of incoming messages to forward, 1 = forwards every message'),(90,18,'ForwardMSG','1','1','Enable Forwarding of BSM'),(91,18,'BSMKafkaTopic','topic.OdeRawEncodedBSMJson','topic.OdeRawEncodedBSMJson','(Cond: ForwardMSG == True) Topic to use for forwarding BSM'),(92,18,'SPaTKafkaTopic','topic.OdeRawEncodedSPATJson','topic.OdeRawEncodedSPATJson','(Cond: ForwardMSG == True) Topic to use for forwarding BSM'),(93,18,'KafkaBrokerIp','172.31.55.238','172.31.55.238','IP address to be used for KAFKA broker'),(94,18,'KafkaBrokerPort','9092','9092','Port number to be used for KAFKA broker'); +INSERT INTO `pluginConfigurationParameter` VALUES (1,1,'SleepMS','100','100','The length of milliseconds to sleep between processing all messages.'),(2,1,'SSLEnabled','true','true','Enable secure connection using SSL.'),(3,1,'SSLPath','/var/www/plugins/.ssl','/var/www/plugins/.ssl','The path to the directory containing the SSL key and certificate files.'),(4,1,'EventRowLimit','50','50','The maximum number of rows returned for the initial Event Log query.'),(5,1,'DownloadPath','/var/www/download','/var/www/download','The path to the directory where downloaded files will be saved.'),(6,1,'LogLevel','ERROR','ERROR','The log level for this plugin'),(7,2,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(8,2,'MapFile','IVP_GF_CSW.xml','IVP_GF_CSW.xml',''),(9,2,'Snap Interval','300','300','The interval in milliseconds to keep a vehicle within a zone before allowing it to transition out of all zones.'),(10,2,'Vehicle Timeout','2000','2000','Timeout in milliseconds when a vehicle is removed from all zones if a BSM has not been received.'),(11,3,'DMS IP Address','192.168.25.30','192.168.25.30','The IP address of the NTCIP Dynamic Message Sign.'),(12,3,'DMS Port','9090','9090','The port of the NTCIP Dynamic Message Sign.'),(13,3,'Enable DMS','True','True','If true all messages are sent to the Dynamic Message Sign using NTCIP 1203.'),(14,3,'Enable Sign Simulator','True','True','If true all messages are sent to the Sign Simulator using UDP.'),(15,3,'Force Message ID','-1','-1','Immediately activates the message ID specified, then resets back to -1.'),(16,3,'Message 01','','','The text to display on the sign for ID 01 with any formatting (see NTCIP 1203).'),(17,3,'Message 02','[jl3][pt15o0]25[np]MPH','[jl3][pt15o0]25[np]MPH','The text to display on the sign for ID 02 with any formatting (see NTCIP 1203).'),(18,3,'Message 03','[jl3][pt15o0]SLOW[np]DOWN','[jl3][pt15o0]SLOW[np]DOWN','The text to display on the sign for ID 03 with any formatting (see NTCIP 1203).'),(19,3,'Message 04','[jl3][pt15o0]CRVE[np]AHED','[jl3][pt15o0]CRVE[np]AHED','The text to display on the sign for ID 04 with any formatting (see NTCIP 1203).'),(20,3,'Sign Sim IP Address','192.168.25.31','192.168.25.31','The IP address of the Sign Simulator that is the receipient of UDP messages.'),(21,3,'Sign Sim Port','9090','9090','The UDP port of the Sign Simulator that is the receipient of UDP messages.'),(22,4,'Messages_Destination_1','{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"PSM\", \"SendType\": \"PSM\", \"PSID\": \"0x8002\" } ,{ \"TmxType\": \"TMSG07\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\" },{ \"TmxType\": \"TMSG03-P\", \"SendType\": \"TMSG03-P\", \"PSID\": \"0xBFEE\" }] }','{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"PSM\", \"SendType\": \"PSM\", \"PSID\": \"0x8002\" } ,{ \"TmxType\": \"TMSG07\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\" },{ \"TmxType\": \"TMSG03-P\", \"SendType\": \"TMSG03-P\", \"PSID\": \"0xBFEE\" }] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 1.'),(23,4,'Messages_Destination_2','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 2.'),(24,4,'Messages_Destination_3','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 3.'),(25,4,'Messages_Destination_4','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 4.'),(26,4,'Destination_1','127.0.0.1:1516','127.0.0.1:1516','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_1.'),(27,4,'Destination_2','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_2.'),(28,4,'Destination_3','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_3.'),(29,4,'Destination_4','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_4.'),(30,4,'Signature','False','False','True or False value indicating whether to sign the messages.'),(31,5,'Frequency','500','500','Rate to send Location Message in milliseconds'),(32,5,'LatchHeadingSpeed','2.5','2.5','Speed at which the heading parameter should be latched, in mph. Set to 0 to disable latching.'),(33,5,'GPSSource','localhost','localhost','Host where the GPSd is running'),(34,5,'SendRawNMEA','true','true','Route the raw NMEA strings from GPSd through TMX'),(35,6,'Frequency','1000','1000','The frequency to send the MAP message in milliseconds.'),(36,6,'MAP_Files','{ \"MapFiles\": [\n {\"Action\":0, \"FilePath\":\"GID_Telegraph-Twelve_Mile_withEgress.xml\"}\n] }','{ \"MapFiles\": [\n {\"Action\":0, \"FilePath\":\"GID_Telegraph-Twelve_Mile_withEgress.xml\"}\n] }','JSON data defining a list of map files. One map file for each action set specified by the TSC.'),(37,7,'IP','127.0.0.1','127.0.0.1','IP address for the incoming message network connection.'),(38,7,'Port','26789','26789','Port for the incoming message network connection.'),(39,7,'RouteDSRC','false','false','Set the flag to route a received J2735 message over DSRC.'),(40,7,'EnableSimulatedBSM','true','true','Accept and route incoming BSM messages from a V2I Hub simulator.'),(41,7,'EnableSimulatedSRM','true','true','Accept and route incoming SRM messages from a V2I Hub simulator.'),(42,7,'EnableSimulatedLocation','true','true','Accept and route incoming GPS location messages from a V2I Hub simulator.'),(43,8,'ODEIP','127.0.0.1','127.0.0.1','IP address for the ODE network connection.'),(44,8,'ODEPort','26789','26789','Port for the ODE network connection.'),(45,9,'Endpoint IP','156.63.133.118','156.63.133.118','NTRIP caster endpoint IP address'),(46,9,'Endpoint Port','2101','2101','NTRIP caster endpoint port'),(47,9,'Username','username','username','NTRIP caster authentication username'),(48,9,'Password','password','password','NTRIP caster authentication password'),(49,9,'Mountpoint','ODOT_RTCM23','ODOT_RTCM23','NTRIP caster mountpoint'),(50,9,'RTCM Version','Unknown','Unknown','Specify the expected RTCM message version (2.3 or 3.3) coming from the caster. Use Unknown to auto detect the version, which is done using trial and error, thus may be slow.'),(51,9,'Route RTCM','false','false','Route the RTCM messages created from NTRIP internally for use by other plugins.'),(52,10,'Intersection_Id','1','1','The intersection id for SPAT generated by this plugin.'),(53,10,'Intersection_Name','Intersection','Intersection','The intersection name for SPAT generated by this plugin.'),(54,10,'SignalGroupMapping','{\"SignalGroups\":[{\"SignalGroupId\":1,\"Phase\":1,\"Type\":\"vehicle\"},{\"SignalGroupId\":2,\"Phase\":2,\"Type\":\"vehicle\"},{\"SignalGroupId\":3,\"Phase\":3,\"Type\":\"vehicle\"},{\"SignalGroupId\":4,\"Phase\":4,\"Type\":\"vehicle\"},{\"SignalGroupId\":5,\"Phase\":5,\"Type\":\"vehicle\"},{\"SignalGroupId\":6,\"Phase\":6,\"Type\":\"vehicle\"},{\"SignalGroupId\":7,\"Phase\":7,\"Type\":\"vehicle\"},{\"SignalGroupId\":8,\"Phase\":8,\"Type\":\"vehicle\"},{\"SignalGroupId\":22,\"Phase\":2,\"Type\":\"pedestrian\"},{\"SignalGroupId\":24,\"Phase\":4,\"Type\":\"pedestrian\"},{\"SignalGroupId\":26,\"Phase\":6,\"Type\":\"pedestrian\"},{\"SignalGroupId\":28,\"Phase\":8,\"Type\":\"pedestrian\"}]}','{\"SignalGroups\":[{\"SignalGroupId\":1,\"Phase\":1,\"Type\":\"vehicle\"},{\"SignalGroupId\":2,\"Phase\":2,\"Type\":\"vehicle\"},{\"SignalGroupId\":3,\"Phase\":3,\"Type\":\"vehicle\"},{\"SignalGroupId\":4,\"Phase\":4,\"Type\":\"vehicle\"},{\"SignalGroupId\":5,\"Phase\":5,\"Type\":\"vehicle\"},{\"SignalGroupId\":6,\"Phase\":6,\"Type\":\"vehicle\"},{\"SignalGroupId\":7,\"Phase\":7,\"Type\":\"vehicle\"},{\"SignalGroupId\":8,\"Phase\":8,\"Type\":\"vehicle\"},{\"SignalGroupId\":22,\"Phase\":2,\"Type\":\"pedestrian\"},{\"SignalGroupId\":24,\"Phase\":4,\"Type\":\"pedestrian\"},{\"SignalGroupId\":26,\"Phase\":6,\"Type\":\"pedestrian\"},{\"SignalGroupId\":28,\"Phase\":8,\"Type\":\"pedestrian\"}]}','JSON data defining a list of SignalGroups and phases.'),(55,10,'Local_IP','','','The IPv4 address of the local computer for receiving Traffic Signal Controller Broadcast Messages.'),(56,10,'Local_UDP_Port','local port','local port','The local UDP port for reception of Traffic Signal Controller Broadcast Messages from the TSC.'),(57,10,'TSC_IP','','','The IPv4 address of the destination Traffic Signal Controller (TSC).'),(58,10,'TSC_Remote_SNMP_Port','','','The destination port on the Traffic Signal Controller (TSC) for SNMP NTCIP communication.'),(59,11,'Instance','0','0','The instance of Preemption plugin.'),(60,11,'BasePreemptionOid','.1.3.6.1.4.1.1206.4.2.1.6.3.1.2.','.1.3.6.1.4.1.1206.4.2.1.6.3.1.2.','The BasePreemptionOid of Preemption plugin.'),(61,11,'ipwithport',':',':','The ipwithport of Preemption plugin.'),(62,11,'snmp_community','public','public','The snmp_community of Preemption plugin.'),(63,11,'map_path','/geo.json','/geo.json','The map_path for Preemption plugin.'),(64,11,'allowedList','{\"validVehicles\":[\"292710445\",\"123456789\",\"2345678\"]}','{\"validVehicles\":[\"292710445\",\"123456789\",\"2345678\"]}','List of vehicles BSM id that are allowed'),(65,12,'File Size In MB','100','100','Maximum size of the SPaT log file in mb.'),(66,12,'Filename','spatTx','spatTx','Default name of the SPaT log file.'),(67,12,'File Location','/var/log/tmx','/var/log/tmx','The location where the log files are stored. DO NOT edit while using docker deployment of V2X-Hub!'),(68,13,'File Size In MB','100','100','Maximum size of the BSM log file in mb.'),(69,13,'Filename','bsmTx','bsmTx','Default name of the BSM log file.'),(70,13,'File Location','/var/log/tmx','/var/log/tmx','The location where the log files are stored. DO NOT edit while using docker deployment of V2X-Hub!'),(71,14,'Frequency','1000','1000','The frequency to send the PSM in milliseconds.'),(72,14,'Instance','0','0','The instance of Pedestrian plugin.'),(73,14,'WebServiceIP','127.0.0.1','127.0.0.1','IP address at which the web service exists'),(74,14,'WebServicePort','9000','9000','Port at which Web service exists'),(75,15,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(76,15,'MapFile','/var/www/plugins/MAP/IVP_GF_TIM.xml','/var/www/plugins/MAP/IVP_GF_TIM.xml',''),(77,15,'Start_Broadcast_Date','01-01-2019','01-01-2019','The Start Broadcast Date for the TIM message in the (mm-dd-YYYY) format.'),(78,15,'Stop_Broadcast_Date','12-31-2020','12-31-2020','The Stop Broadcast Date for the TIM message in the (mm-dd-YYYY) format.'),(79,15,'Start_Broadcast_Time','06:00:00','06:00:00','The Start Broadcast Time for the TIM message in the (HH:MM:SS) format.'),(80,15,'Stop_Broadcast_Time','21:00:00','21:00:00','The Start Broadcast Time for the TIM message in the (HH:MM:SS) format.'),(81,15,'WebServiceIP','127.0.0.1','127.0.0.1','IP address at which the web service exists'),(82,15,'WebServicePort','10000','10000','Port at which Web service exists'),(83,16,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(84,16,'Instance','0','0','The instance of this plugin.'),(85,16,'WebServiceIP','127.0.0.1','127.0.0.1','Server IP address for V2X hub'),(86,16,'WebServicePort','22222','22222','Server Port for V2X hub'),(87,17,'Database_IP','127.0.0.1','127.0.0.1','IP address of database'),(88,17,'Database_Port','3306','3306','Port of database'),(89,17,'Database_Username','root','root','Username for database'),(90,17,'Database_Password','ivp','ivp','Password for database'),(91,17,'Database_Name','PORT_DRAYAGE','PORT_DRAYAGE','Name of database'),(92,17,'LogLevel','INFO','INFO','The log level for this plugin'),(93,18,'instance','1','1','instance of the application'),(94,18,'schedule_frequency','1','1','sample of incoming messages to forward, 1 = forwards every message'),(95,18,'ForwardMSG','1','1','Enable Forwarding of BSM'),(96,18,'BSMKafkaTopic','topic.OdeRawEncodedBSMJson','topic.OdeRawEncodedBSMJson','(Cond: ForwardMSG == True) Topic to use for forwarding BSM'),(97,18,'SPaTKafkaTopic','topic.OdeRawEncodedSPATJson','topic.OdeRawEncodedSPATJson','(Cond: ForwardMSG == True) Topic to use for forwarding BSM'),(98,18,'KafkaBrokerIp','172.31.55.238','172.31.55.238','IP address to be used for KAFKA broker'),(99,18,'KafkaBrokerPort','9092','9092','Port number to be used for KAFKA broker'),(100,19,'Startup Delay (ms)','10000','10000','Delay in milliseconds before starting any plugins.'),(101,19,'Monitor Check Interval (ms)','5000','5000','Delay in milliseconds between monitor checks.'),(102,19,'Max Startup Time (ms)','15000','15000','Maximum allowed startup time of a plugin before it is rebooted.'),(103,20,'Database Refresh Interval (ms)','2000','2000','The interval (in milliseconds) between uploads of message statistics to the database.'),(104,20,'Message Averaging Window (ms)','20000','20000','The averaging window (in milliseconds) that the profiler measures average interval.'),(105,21,'Purge Intervals (sec)','120','120','Interval between purges of history items'),(106,21,'Max Event Log Size','2000','2000','Maximum number of event log entries to keep. A value of zero will result in no purging of event log entries'); /*!40000 ALTER TABLE `pluginConfigurationParameter` ENABLE KEYS */; UNLOCK TABLES; @@ -247,7 +247,7 @@ CREATE TABLE `pluginMessageMap` ( KEY `messageTypeId` (`messageTypeId`), CONSTRAINT `pluginMessageMap_ibfk_1` FOREIGN KEY (`pluginId`) REFERENCES `plugin` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `pluginMessageMap_ibfk_2` FOREIGN KEY (`messageTypeId`) REFERENCES `messageType` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB AUTO_INCREMENT=1362 DEFAULT CHARSET=latin1 COMMENT='This table identifies the types of messages generated by each plugin.'; +) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=latin1 COMMENT='This table identifies the types of messages generated by each plugin.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -256,7 +256,7 @@ CREATE TABLE `pluginMessageMap` ( LOCK TABLES `pluginMessageMap` WRITE; /*!40000 ALTER TABLE `pluginMessageMap` DISABLE KEYS */; -INSERT INTO `pluginMessageMap` VALUES (1,1,15),(1361,7,1),(70,7,15),(75,13,15); +INSERT INTO `pluginMessageMap` VALUES (1,1,15),(1361,7,1),(70,7,15),(75,13,15),(1538,15,14),(1435,17,30); /*!40000 ALTER TABLE `pluginMessageMap` ENABLE KEYS */; UNLOCK TABLES; @@ -276,7 +276,7 @@ CREATE TABLE `pluginStatus` ( UNIQUE KEY `UQ_pluginId_key` (`pluginId`,`key`), KEY `pluginId` (`pluginId`), CONSTRAINT `pluginStatus_ibfk_2` FOREIGN KEY (`pluginId`) REFERENCES `plugin` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -302,7 +302,7 @@ CREATE TABLE `systemConfigurationParameter` ( `defaultValue` text NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `key` (`key`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 COMMENT='This table lists the IVP system configuration parameters used by both core components and plugins to control the behavior of the system.'; +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 COMMENT='This table lists the IVP system configuration parameters used by both core components and plugins to control the behavior of the system.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -330,7 +330,7 @@ CREATE TABLE `user` ( PRIMARY KEY (`id`), UNIQUE KEY `UQ_user_id` (`id`), UNIQUE KEY `UQ_user_username` (`username`) -) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 COMMENT='The list of accounts that can access the IVP platform via the administrative portal is held in the users table.'; +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1 COMMENT='The list of accounts that can access the IVP platform via the administrative portal is held in the users table.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -351,4 +351,4 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2021-06-23 23:52:23 +-- Dump completed on 2021-08-25 13:36:29 diff --git a/configuration/amd64/mysql/port_drayage.sql b/configuration/amd64/mysql/port_drayage.sql new file mode 100644 index 000000000..eccdb199b --- /dev/null +++ b/configuration/amd64/mysql/port_drayage.sql @@ -0,0 +1,91 @@ +-- MySQL dump 10.13 Distrib 5.7.34, for Linux (x86_64) +-- +-- Host: 127.0.0.1 Database: PORT_DRAYAGE +-- ------------------------------------------------------ +-- Server version 5.7.35 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `PORT_DRAYAGE` +-- + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `PORT_DRAYAGE` /*!40100 DEFAULT CHARACTER SET latin1 */; + +USE `PORT_DRAYAGE`; + +-- +-- Table structure for table `first_action` +-- + +DROP TABLE IF EXISTS `first_action`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `first_action` ( + `cmv_id` varchar(20) NOT NULL, + `cargo_id` varchar(20) DEFAULT NULL, + `destination_lat` decimal(9,7) NOT NULL, + `destination_long` decimal(9,7) NOT NULL, + `operation` varchar(20) NOT NULL, + `action_id` varchar(36) NOT NULL, + `next_action` varchar(36) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `first_action` +-- + +LOCK TABLES `first_action` WRITE; +/*!40000 ALTER TABLE `first_action` DISABLE KEYS */; +INSERT INTO `first_action` VALUES ("123",'SOME_CARGO',38.9548890,-77.1481430,'PICKUP','4bea1c45-e421-11eb-a8cc-000c29ae389d','32320c8a-e422-11eb-a8cc-000c29ae389d'); +/*!40000 ALTER TABLE `first_action` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `freight` +-- + +DROP TABLE IF EXISTS `freight`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `freight` ( + `cmv_id` varchar(20) NOT NULL, + `cargo_id` varchar(20) DEFAULT NULL, + `destination_lat` decimal(9,7) NOT NULL, + `destination_long` decimal(9,7) NOT NULL, + `operation` varchar(20) NOT NULL, + `action_id` varchar(36) NOT NULL, + `next_action` varchar(36) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `freight` +-- + +LOCK TABLES `freight` WRITE; +/*!40000 ALTER TABLE `freight` DISABLE KEYS */; +INSERT INTO `freight` VALUES ("123",NULL,38.9549780,-77.1475790,'EXIT_STAGING_AREA','32320c8a-e422-11eb-a8cc-000c29ae389d','4ace39e6-ee36-11eb-9a03-0242ac130003'),("123",'SOME_CARGO',38.9548890,-77.1481430,'PICKUP','4bea1c45-e421-11eb-a8cc-000c29ae389d','32320c8a-e422-11eb-a8cc-000c29ae389d'); +/*!40000 ALTER TABLE `freight` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2021-07-21 11:42:55 diff --git a/configuration/amd64/mysql/suntrax/port_area_operations.sql b/configuration/amd64/mysql/suntrax/port_area_operations.sql new file mode 100644 index 000000000..abeb6e478 --- /dev/null +++ b/configuration/amd64/mysql/suntrax/port_area_operations.sql @@ -0,0 +1,90 @@ +-- MySQL dump 10.13 Distrib 5.7.36, for Linux (x86_64) +-- +-- Host: 127.0.0.1 Database: PORT_DRAYAGE +-- ------------------------------------------------------ +-- Server version 5.7.36 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `PORT_DRAYAGE` +-- + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `PORT_DRAYAGE` /*!40100 DEFAULT CHARACTER SET latin1 */; + +USE `PORT_DRAYAGE`; + +-- +-- Table structure for table `first_action` +-- + +DROP TABLE IF EXISTS `first_action`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `first_action` ( + `cmv_id` varchar(20) NOT NULL, + `cargo_id` varchar(20) DEFAULT NULL, + `destination_lat` decimal(9,7) NOT NULL, + `destination_long` decimal(9,7) NOT NULL, + `operation` varchar(20) NOT NULL, + `action_id` varchar(36) NOT NULL, + `next_action` varchar(36) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `first_action` +-- + +LOCK TABLES `first_action` WRITE; +/*!40000 ALTER TABLE `first_action` DISABLE KEYS */; +/*!40000 ALTER TABLE `first_action` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `freight` +-- + +DROP TABLE IF EXISTS `freight`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `freight` ( + `cmv_id` varchar(20) NOT NULL, + `cargo_id` varchar(20) DEFAULT NULL, + `destination_lat` decimal(9,7) NOT NULL, + `destination_long` decimal(9,7) NOT NULL, + `operation` varchar(20) NOT NULL, + `action_id` varchar(36) NOT NULL, + `next_action` varchar(36) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `freight` +-- + +LOCK TABLES `freight` WRITE; +/*!40000 ALTER TABLE `freight` DISABLE KEYS */; +INSERT INTO `freight` VALUES ('DOT-80550',NULL,28.1128156,-81.8314745,'ENTER_PORT','4ace39e6-ee36-11eb-9a03-0242ac130003','67eadd3a-38b4-11ec-930a-000145098e4f'),('DOT-80550','CARGO_A',28.1119763,-81.8312035,'DROPOFF','67eadd3a-38b4-11ec-930a-000145098e4f','0bf7ebda-38b5-11ec-930a-000145098e4f'),('DOT-80550','CARGO_B',28.1117373,-81.8309654,'PICKUP','0bf7ebda-38b5-11ec-930a-000145098e4f','9230504d-38b5-11ec-930a-000145098e4f'),('DOT-80550','CARGO_B',28.1120500,-81.8306483,'PORT_CHECKPOINT','9230504d-38b5-11ec-930a-000145098e4f','511ad052-38b6-11ec-930a-000145098e4f'),('DOT-80550','CARGO_B',28.1138052,-81.8317502,'EXIT_PORT','511ad052-38b6-11ec-930a-000145098e4f','fc15d52a-3c0c-11ec-b00d-000145098e4f'),('DOT-80550','CARGO_B',28.1232336,-81.8347566,'ENTER_STAGING_AREA','fc15d52a-3c0c-11ec-b00d-000145098e4f','5ceaab82-515c-11ec-9e2c-000145098e47'),('DOT-10004',NULL,28.1128156,-81.8314745,'ENTER_PORT','84f6b797-52c2-11ec-9105-000145098e4f','c9bba171-52c2-11ec-9105-000145098e4f'),('DOT-10004','CARGO_A',28.1119763,-81.8312035,'DROPOFF','c9bba171-52c2-11ec-9105-000145098e4f','8e1d456a-52c3-11ec-9105-000145098e4f'),('DOT-10004','CARGO_B',28.1117373,-81.8309654,'PICKUP','8e1d456a-52c3-11ec-9105-000145098e4f','744be658-52c4-11ec-9105-000145098e4f'),('DOT-10004','CARGO_B',28.1120500,-81.8306483,'PORT_CHECKPOINT','744be658-52c4-11ec-9105-000145098e4f','a4b419b9-52c5-11ec-9105-000145098e4f'),('DOT-10004','CARGO_B',28.1138052,-81.8317502,'EXIT_PORT','a4b419b9-52c5-11ec-9105-000145098e4f','20b546e3-52c6-11ec-9105-000145098e4f'),('DOT-10004','CARGO_B',28.1232336,-81.8347566,'ENTER_STAGING_AREA','20b546e3-52c6-11ec-9105-000145098e4f','53875eba-52c7-11ec-9105-000145098e4f'); +/*!40000 ALTER TABLE `freight` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2021-12-03 11:03:12 diff --git a/configuration/amd64/mysql/suntrax/staging_area_operations.sql b/configuration/amd64/mysql/suntrax/staging_area_operations.sql new file mode 100644 index 000000000..7332feb90 --- /dev/null +++ b/configuration/amd64/mysql/suntrax/staging_area_operations.sql @@ -0,0 +1,91 @@ +-- MySQL dump 10.13 Distrib 5.7.36, for Linux (x86_64) +-- +-- Host: 127.0.0.1 Database: PORT_DRAYAGE +-- ------------------------------------------------------ +-- Server version 5.7.36 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `PORT_DRAYAGE` +-- + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `PORT_DRAYAGE` /*!40100 DEFAULT CHARACTER SET latin1 */; + +USE `PORT_DRAYAGE`; + +-- +-- Table structure for table `first_action` +-- + +DROP TABLE IF EXISTS `first_action`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `first_action` ( + `cmv_id` varchar(20) NOT NULL, + `cargo_id` varchar(20) DEFAULT NULL, + `destination_lat` decimal(9,7) NOT NULL, + `destination_long` decimal(9,7) NOT NULL, + `operation` varchar(20) NOT NULL, + `action_id` varchar(36) NOT NULL, + `next_action` varchar(36) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `first_action` +-- + +LOCK TABLES `first_action` WRITE; +/*!40000 ALTER TABLE `first_action` DISABLE KEYS */; +INSERT INTO `first_action` VALUES ('DOT-80550','CARGO_A',28.1249788,-81.8348897,'PICKUP','4bea1c45-e421-11eb-a8cc-000c29ae389d','32320c8a-e422-11eb-a8cc-000c29ae389d'),('DOT-10004','CARGO_A',28.1249788,-81.8348897,'PICKUP','66bba4a0-52c1-11ec-9105-000145098e4f','66bba4cb-52c1-11ec-9105-000145098e4f'); +/*!40000 ALTER TABLE `first_action` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `freight` +-- + +DROP TABLE IF EXISTS `freight`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `freight` ( + `cmv_id` varchar(20) NOT NULL, + `cargo_id` varchar(20) DEFAULT NULL, + `destination_lat` decimal(9,7) NOT NULL, + `destination_long` decimal(9,7) NOT NULL, + `operation` varchar(20) NOT NULL, + `action_id` varchar(36) NOT NULL, + `next_action` varchar(36) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `freight` +-- + +LOCK TABLES `freight` WRITE; +/*!40000 ALTER TABLE `freight` DISABLE KEYS */; +INSERT INTO `freight` VALUES ('DOT-80550',NULL,28.1232195,-81.8348278,'EXIT_STAGING_AREA','32320c8a-e422-11eb-a8cc-000c29ae389d','4ace39e6-ee36-11eb-9a03-0242ac130003'),('DOT-80550','CARGO_A',28.1249788,-81.8348897,'PICKUP','4bea1c45-e421-11eb-a8cc-000c29ae389d','32320c8a-e422-11eb-a8cc-000c29ae389d'),('DOT-80550',NULL,28.1128156,-81.8314745,'ENTER_PORT','4ace39e6-ee36-11eb-9a03-0242ac130003','67eadd3a-38b4-11ec-930a-000145098e4f'),('DOT-80550','CARGO_B',28.1232336,-81.8347566,'ENTER_STAGING_AREA','fc15d52a-3c0c-11ec-b00d-000145098e4f','5ceaab82-515c-11ec-9e2c-000145098e47'),('DOT-10004','CARGO_A',28.1249788,-81.8348897,'PICKUP','66bba4a0-52c1-11ec-9105-000145098e4f','66bba4cb-52c1-11ec-9105-000145098e4f'),('DOT-10004',NULL,28.1232195,-81.8348278,'EXIT_STAGING_AREA','66bba4cb-52c1-11ec-9105-000145098e4f','84f6b797-52c2-11ec-9105-000145098e4f'),('DOT-10004',NULL,28.1128156,-81.8314745,'ENTER_PORT','84f6b797-52c2-11ec-9105-000145098e4f','c9bba171-52c2-11ec-9105-000145098e4f'),('DOT-10004','CARGO_B',28.1232336,-81.8347566,'ENTER_STAGING_AREA','20b546e3-52c6-11ec-9105-000145098e4f','53875eba-52c7-11ec-9105-000145098e4f'); +/*!40000 ALTER TABLE `freight` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2021-12-03 11:25:03 diff --git a/configuration/arm64/docker-compose.yml b/configuration/arm64/docker-compose.yml index cab2e4176..b63d9df3f 100644 --- a/configuration/arm64/docker-compose.yml +++ b/configuration/arm64/docker-compose.yml @@ -15,13 +15,12 @@ services: - mysql_password - mysql_root_password volumes: - - ./mysql/localhost.sql:/docker-entrypoint-initdb.d/localhost.sql + - "mysql_db:/var/lib/mysql" + - ./mysql/:/docker-entrypoint-initdb.d/ php: - image: php:7.2.2-apache + image: usdotfhwaops/php:6.2 container_name: php - volumes: - - ../../web/:/var/www/html/ network_mode: host depends_on: - db @@ -29,7 +28,7 @@ services: tty: true v2xhub: - image: usdotfhwaops/v2xhubarm:latest + image: usdotfhwaops/v2xhubarm:6.2 container_name: v2xhub network_mode: host restart: always @@ -42,6 +41,10 @@ services: volumes: - ./logs:/var/log/tmx - ./MAP:/var/www/plugins/MAP + port_drayage_webservice: + image: usdotfhwaops/port-drayage-webservice:6.2 + container_name: port_drayage_webservice + network_mode: host secrets: mysql_password: file: ./secrets/mysql_password.txt diff --git a/configuration/arm64/mysql/localhost.sql b/configuration/arm64/mysql/localhost.sql index 0430a75cf..12b072cc7 100644 --- a/configuration/arm64/mysql/localhost.sql +++ b/configuration/arm64/mysql/localhost.sql @@ -1,8 +1,8 @@ --- MySQL dump 10.13 Distrib 5.7.34, for Linux (x86_64) +-- MySQL dump 10.13 Distrib 5.7.35, for Linux (x86_64) -- --- Host: localhost Database: IVP +-- Host: 127.0.0.1 Database: IVP -- ------------------------------------------------------ --- Server version 5.7.34 +-- Server version 5.7.35 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -38,7 +38,7 @@ CREATE TABLE `eventLog` ( `logLevel` enum('Debug','Info','Warning','Error','Fatal') NOT NULL COMMENT 'The type of event being logged, one of - Debug - Info - Warn - Error', `uploaded` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='This table records events generated by every IVP core component and plugin in the IVP platform. '; +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1 COMMENT='This table records events generated by every IVP core component and plugin in the IVP platform. '; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -78,7 +78,7 @@ CREATE TABLE `installedPlugin` ( LOCK TABLES `installedPlugin` WRITE; /*!40000 ALTER TABLE `installedPlugin` DISABLE KEYS */; -INSERT INTO `installedPlugin` VALUES (1,1,'/var/www/plugins/CommandPlugin','/bin/CommandPlugin','manifest.json','',0,500000),(2,2,'/var/www/plugins/CswPlugin','/bin/CswPlugin','manifest.json','',0,500000),(3,3,'/var/www/plugins/DmsPlugin','/bin/DmsPlugin','manifest.json','',0,500000),(4,4,'/var/www/plugins/DsrcImmediateForwardPlugin','/bin/DsrcImmediateForwardPlugin','manifest.json','',0,500000),(5,5,'/var/www/plugins/LocationPlugin','/bin/LocationPlugin','manifest.json','',0,500000),(6,6,'/var/www/plugins/MapPlugin','/bin/MapPlugin','manifest.json','',0,500000),(7,7,'/var/www/plugins/MessageReceiverPlugin','/bin/MessageReceiverPlugin','manifest.json','',0,500000),(8,8,'/var/www/plugins/ODEPlugin','/bin/ODEPlugin','manifest.json','',0,500000),(9,9,'/var/www/plugins/RtcmPlugin','/bin/RtcmPlugin','manifest.json','',0,500000),(10,10,'/var/www/plugins/SpatPlugin','/bin/SpatPlugin','manifest.json','',0,500000),(11,11,'/var/www/plugins/PreemptionPlugin','/bin/PreemptionPlugin','manifest.json','',0,500000),(12,12,'/var/www/plugins/SPaTLoggerPlugin','/bin/SPaTLoggerPlugin','manifest.json','',0,500000),(13,13,'/var/www/plugins/MessageLoggerPlugin','/bin/MessageLoggerPlugin','manifest.json','',0,500000),(14,14,'/var/www/plugins/PedestrianPlugin','/bin/PedestrianPlugin','manifest.json','',0,500000),(15,15,'/var/www/plugins/TimPlugin','/bin/TimPlugin','manifest.json','',0,500000),(16,16,'/var/www/plugins/CARMACloudPlugin','/bin/CARMACloudPlugin','manifest.json','',0,500000),(17,17,'/var/www/plugins/MobilityOperationPlugin','/bin/MobilityOperationPlugin','manifest.json','',0,500000),(18,18,'/var/www/plugins/ODELoggerPlugin','/bin/ODELoggerPlugin','manifest.json','',0,500000); +INSERT INTO `installedPlugin` VALUES (1,1,'/var/www/plugins/CommandPlugin','/bin/CommandPlugin','manifest.json','',1,500000),(2,2,'/var/www/plugins/CswPlugin','/bin/CswPlugin','manifest.json','',0,500000),(3,3,'/var/www/plugins/DmsPlugin','/bin/DmsPlugin','manifest.json','',0,500000),(4,4,'/var/www/plugins/DsrcImmediateForwardPlugin','/bin/DsrcImmediateForwardPlugin','manifest.json','',0,500000),(5,5,'/var/www/plugins/LocationPlugin','/bin/LocationPlugin','manifest.json','',0,500000),(6,6,'/var/www/plugins/MapPlugin','/bin/MapPlugin','manifest.json','',0,500000),(7,7,'/var/www/plugins/MessageReceiverPlugin','/bin/MessageReceiverPlugin','manifest.json','',0,500000),(8,8,'/var/www/plugins/ODEPlugin','/bin/ODEPlugin','manifest.json','',0,500000),(9,9,'/var/www/plugins/RtcmPlugin','/bin/RtcmPlugin','manifest.json','',0,500000),(10,10,'/var/www/plugins/SpatPlugin','/bin/SpatPlugin','manifest.json','',0,500000),(11,11,'/var/www/plugins/PreemptionPlugin','/bin/PreemptionPlugin','manifest.json','',0,500000),(12,12,'/var/www/plugins/SPaTLoggerPlugin','/bin/SPaTLoggerPlugin','manifest.json','',0,500000),(13,13,'/var/www/plugins/MessageLoggerPlugin','/bin/MessageLoggerPlugin','manifest.json','',0,500000),(14,14,'/var/www/plugins/PedestrianPlugin','/bin/PedestrianPlugin','manifest.json','',0,500000),(15,15,'/var/www/plugins/TimPlugin','/bin/TimPlugin','manifest.json','',0,500000),(16,16,'/var/www/plugins/CARMACloudPlugin','/bin/CARMACloudPlugin','manifest.json','',0,500000),(17,17,'/var/www/plugins/PortDrayagePlugin','/bin/PortDrayagePlugin','manifest.json','',0,500000),(18,18,'/var/www/plugins/ODELoggerPlugin','/bin/ODELoggerPlugin','manifest.json','',0,500000); /*!40000 ALTER TABLE `installedPlugin` ENABLE KEYS */; UNLOCK TABLES; @@ -102,7 +102,7 @@ CREATE TABLE `messageActivity` ( KEY `pluginId` (`pluginId`), CONSTRAINT `messageActivity_ibfk_1` FOREIGN KEY (`messageTypeId`) REFERENCES `messageType` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `messageActivity_ibfk_2` FOREIGN KEY (`pluginId`) REFERENCES `plugin` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='This table records the most recent message activity of each active plugin in the IVP system. The data in this table is updated by the IVP plugin monitor core component for every message the plugin monitor receives.'; +) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=latin1 COMMENT='This table records the most recent message activity of each active plugin in the IVP system. The data in this table is updated by the IVP plugin monitor core component for every message the plugin monitor receives.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -155,7 +155,7 @@ CREATE TABLE `plugin` ( `version` text, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) -) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=latin1 COMMENT='This table lists the plugins loaded and available to run on the IVP platform.'; +) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=latin1 COMMENT='This table lists the plugins loaded and available to run on the IVP platform.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -164,7 +164,7 @@ CREATE TABLE `plugin` ( LOCK TABLES `plugin` WRITE; /*!40000 ALTER TABLE `plugin` DISABLE KEYS */; -INSERT INTO `plugin` VALUES (1,'CommandPlugin','Listens for websocket connections from the TMX admin portal and processes commands','5.0'),(2,'CSW','Provides Curve Speed Warning (CSW).','5.0'),(3,'DynamicMessageSign','Provides communication to a dynamic message sign.','5.0'),(4,'DSRCMessageManager','Plugin that listens for TMX messages and forwards them to the DSRC Radio (i.e. the RSU).','5.0'),(5,'Location','Plugin used to send out Location Messages using data from GPSD','5.0'),(6,'MAP','Plugin that reads intersection geometry from a configuration file and publishes a J2735 MAP message.','5.0'),(7,'MessageReceiver','Plugin to receive messages from an external DSRC radio or other source','5.0'),(8,'ODEPlugin','Plugin to forward messages to the Florida ODEPlugin network','5.0'),(9,'RTCM','Plugin to listen for RTCM messages from an NTRIP caster and route those messages over DSRC','5.0'),(10,'SPAT','Plugin that reads PTLM data from a configuration file, receives live data from the signal controller, and publishes a J2735 SPAT message.','5.0'),(11,'Preemption','Preemption plugin for the IVP system.','5.0'),(12,'SPaTLoggerPlugin','Listens for SPaT messages and logs them in a file in CSV format.','5.0'),(13,'MessageLoggerPlugin','Listens for J2735 messages and logs them in a file in JSON format.','5.0'),(14,'Pedestrian','Pedestrian plugin for the IVP system.','5.0'),(15,'TIM','Provides Traveller Information Message (TIM).','5.0'),(16,'CARMACloud','CARMA cloud plugin for making websocket connection with CARMA cloud .','5.0'),(17,'MobilityOperationPlugin','In development','5.0'),(18,'ODELoggerPlugin','Listens for J2735 messages and realtime forwards them to ODE.','5.0'); +INSERT INTO `plugin` VALUES (0,'Plugin System','The global configuration for all TMX plugins','4.0'),(1,'CommandPlugin','Listens for websocket connections from the TMX admin portal and processes commands','5.0'),(2,'CSW','Provides Curve Speed Warning (CSW).','5.0'),(3,'DynamicMessageSign','Provides communication to a dynamic message sign.','5.0'),(4,'DSRCMessageManager','Plugin that listens for TMX messages and forwards them to the DSRC Radio (i.e. the RSU).','5.0'),(5,'Location','Plugin used to send out Location Messages using data from GPSD','5.0'),(6,'MAP','Plugin that reads intersection geometry from a configuration file and publishes a J2735 MAP message.','5.0'),(7,'MessageReceiver','Plugin to receive messages from an external DSRC radio or other source','5.0'),(8,'ODEPlugin','Plugin to forward messages to the Florida ODEPlugin network','5.0'),(9,'RTCM','Plugin to listen for RTCM messages from an NTRIP caster and route those messages over DSRC','5.0'),(10,'SPAT','Plugin that reads PTLM data from a configuration file, receives live data from the signal controller, and publishes a J2735 SPAT message.','5.0'),(11,'Preemption','Preemption plugin for the IVP system.','5.0'),(12,'SPaTLoggerPlugin','Listens for SPaT messages and logs them in a file in CSV format.','5.0'),(13,'MessageLoggerPlugin','Listens for J2735 messages and logs them in a file in JSON format.','5.0'),(14,'Pedestrian','Pedestrian plugin for the IVP system.','5.0'),(15,'TIM','Provides Traveller Information Message (TIM).','5.0'),(16,'CARMACloud','CARMA cloud plugin for making websocket connection with CARMA cloud .','3.0.0'),(17,'PortDrayagePlugin','PortDrayagePlugin for sending freight trucks automated actions in a port.','5.0'),(18,'ODELoggerPlugin','Listens for J2735 messages and realtime forwards them to ODE.','5.0'),(19,'ivpcore.PluginMonitor','Core element that is responsible for starting/stopping installed plugins and monitoring the status of the plugins','3.2.0'),(20,'ivpcore.MessageProfiler','Core element that is responsible for profiling the statistics of received messages','3.2.0'),(21,'ivpcore.HistoryManager','Core element that is responsible for purging old log and history data','3.2.0'); /*!40000 ALTER TABLE `plugin` ENABLE KEYS */; UNLOCK TABLES; @@ -217,7 +217,7 @@ CREATE TABLE `pluginConfigurationParameter` ( UNIQUE KEY `pluginId_key` (`pluginId`,`key`), KEY `pluginId` (`pluginId`), CONSTRAINT `pluginConfigurationParameter_ibfk_1` FOREIGN KEY (`pluginId`) REFERENCES `plugin` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB AUTO_INCREMENT=95 DEFAULT CHARSET=latin1 COMMENT='This table lists the IVP system configuration parameters used by both core components and plugins to control the behavior of the system.'; +) ENGINE=InnoDB AUTO_INCREMENT=113 DEFAULT CHARSET=latin1 COMMENT='This table lists the IVP system configuration parameters used by both core components and plugins to control the behavior of the system.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -226,7 +226,7 @@ CREATE TABLE `pluginConfigurationParameter` ( LOCK TABLES `pluginConfigurationParameter` WRITE; /*!40000 ALTER TABLE `pluginConfigurationParameter` DISABLE KEYS */; -INSERT INTO `pluginConfigurationParameter` VALUES (1,1,'SleepMS','100','100','The length of milliseconds to sleep between processing all messages.'),(2,1,'SSLEnabled','true','true','Enable secure connection using SSL.'),(3,1,'SSLPath','/var/www/plugins/.ssl','/var/www/plugins/.ssl','The path to the directory containing the SSL key and certificate files.'),(4,1,'EventRowLimit','50','50','The maximum number of rows returned for the initial Event Log query.'),(5,1,'DownloadPath','/var/www/download','/var/www/download','The path to the directory where downloaded files will be saved.'),(6,1,'LogLevel','ERROR','ERROR','The log level for this plugin'),(7,2,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(8,2,'MapFile','IVP_GF_CSW.xml','IVP_GF_CSW.xml',''),(9,2,'Snap Interval','300','300','The interval in milliseconds to keep a vehicle within a zone before allowing it to transition out of all zones.'),(10,2,'Vehicle Timeout','2000','2000','Timeout in milliseconds when a vehicle is removed from all zones if a BSM has not been received.'),(11,3,'DMS IP Address','192.168.25.30','192.168.25.30','The IP address of the NTCIP Dynamic Message Sign.'),(12,3,'DMS Port','9090','9090','The port of the NTCIP Dynamic Message Sign.'),(13,3,'Enable DMS','True','True','If true all messages are sent to the Dynamic Message Sign using NTCIP 1203.'),(14,3,'Enable Sign Simulator','True','True','If true all messages are sent to the Sign Simulator using UDP.'),(15,3,'Force Message ID','-1','-1','Immediately activates the message ID specified, then resets back to -1.'),(16,3,'Message 01','','','The text to display on the sign for ID 01 with any formatting (see NTCIP 1203).'),(17,3,'Message 02','[jl3][pt15o0]25[np]MPH','[jl3][pt15o0]25[np]MPH','The text to display on the sign for ID 02 with any formatting (see NTCIP 1203).'),(18,3,'Message 03','[jl3][pt15o0]SLOW[np]DOWN','[jl3][pt15o0]SLOW[np]DOWN','The text to display on the sign for ID 03 with any formatting (see NTCIP 1203).'),(19,3,'Message 04','[jl3][pt15o0]CRVE[np]AHED','[jl3][pt15o0]CRVE[np]AHED','The text to display on the sign for ID 04 with any formatting (see NTCIP 1203).'),(20,3,'Sign Sim IP Address','192.168.25.31','192.168.25.31','The IP address of the Sign Simulator that is the receipient of UDP messages.'),(21,3,'Sign Sim Port','9090','9090','The UDP port of the Sign Simulator that is the receipient of UDP messages.'),(22,4,'Messages_Destination_1','{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"PSM\", \"SendType\": \"PSM\", \"PSID\": \"0x8002\" } ,{ \"TmxType\": \"TMSG07\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\" }] }','{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"PSM\", \"SendType\": \"PSM\", \"PSID\": \"0x8002\" } ,{ \"TmxType\": \"TMSG07\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\" }] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 1.'),(23,4,'Messages_Destination_2','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 2.'),(24,4,'Messages_Destination_3','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 3.'),(25,4,'Messages_Destination_4','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 4.'),(26,4,'Destination_1','127.0.0.1:1516','127.0.0.1:1516','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_1.'),(27,4,'Destination_2','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_2.'),(28,4,'Destination_3','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_3.'),(29,4,'Destination_4','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_4.'),(30,4,'Signature','False','False','True or False value indicating whether to sign the messages.'),(31,5,'Frequency','500','500','Rate to send Location Message in milliseconds'),(32,5,'LatchHeadingSpeed','2.5','2.5','Speed at which the heading parameter should be latched, in mph. Set to 0 to disable latching.'),(33,5,'GPSSource','localhost','localhost','Host where the GPSd is running'),(34,5,'SendRawNMEA','true','true','Route the raw NMEA strings from GPSd through TMX'),(35,6,'Frequency','1000','1000','The frequency to send the MAP message in milliseconds.'),(36,6,'MAP_Files','{ \"MapFiles\": [\n {\"Action\":0, \"FilePath\":\"GID_Telegraph-Twelve_Mile_withEgress.xml\"}\n] }','{ \"MapFiles\": [\n {\"Action\":0, \"FilePath\":\"GID_Telegraph-Twelve_Mile_withEgress.xml\"}\n] }','JSON data defining a list of map files. One map file for each action set specified by the TSC.'),(37,7,'IP','127.0.0.1','127.0.0.1','IP address for the incoming message network connection.'),(38,7,'Port','26789','26789','Port for the incoming message network connection.'),(39,7,'RouteDSRC','false','false','Set the flag to route a received J2735 message over DSRC.'),(40,7,'EnableSimulatedBSM','true','true','Accept and route incoming BSM messages from a V2I Hub simulator.'),(41,7,'EnableSimulatedSRM','true','true','Accept and route incoming SRM messages from a V2I Hub simulator.'),(42,7,'EnableSimulatedLocation','true','true','Accept and route incoming GPS location messages from a V2I Hub simulator.'),(43,8,'ODEIP','127.0.0.1','127.0.0.1','IP address for the ODE network connection.'),(44,8,'ODEPort','26789','26789','Port for the ODE network connection.'),(45,9,'Endpoint IP','156.63.133.118','156.63.133.118','NTRIP caster endpoint IP address'),(46,9,'Endpoint Port','2101','2101','NTRIP caster endpoint port'),(47,9,'Username','username','username','NTRIP caster authentication username'),(48,9,'Password','password','password','NTRIP caster authentication password'),(49,9,'Mountpoint','ODOT_RTCM23','ODOT_RTCM23','NTRIP caster mountpoint'),(50,9,'RTCM Version','Unknown','Unknown','Specify the expected RTCM message version (2.3 or 3.3) coming from the caster. Use Unknown to auto detect the version, which is done using trial and error, thus may be slow.'),(51,9,'Route RTCM','false','false','Route the RTCM messages created from NTRIP internally for use by other plugins.'),(52,10,'Intersection_Id','1','1','The intersection id for SPAT generated by this plugin.'),(53,10,'Intersection_Name','Intersection','Intersection','The intersection name for SPAT generated by this plugin.'),(54,10,'SignalGroupMapping','{\"SignalGroups\":[{\"SignalGroupId\":1,\"Phase\":1,\"Type\":\"vehicle\"},{\"SignalGroupId\":2,\"Phase\":2,\"Type\":\"vehicle\"},{\"SignalGroupId\":3,\"Phase\":3,\"Type\":\"vehicle\"},{\"SignalGroupId\":4,\"Phase\":4,\"Type\":\"vehicle\"},{\"SignalGroupId\":5,\"Phase\":5,\"Type\":\"vehicle\"},{\"SignalGroupId\":6,\"Phase\":6,\"Type\":\"vehicle\"},{\"SignalGroupId\":7,\"Phase\":7,\"Type\":\"vehicle\"},{\"SignalGroupId\":8,\"Phase\":8,\"Type\":\"vehicle\"},{\"SignalGroupId\":22,\"Phase\":2,\"Type\":\"pedestrian\"},{\"SignalGroupId\":24,\"Phase\":4,\"Type\":\"pedestrian\"},{\"SignalGroupId\":26,\"Phase\":6,\"Type\":\"pedestrian\"},{\"SignalGroupId\":28,\"Phase\":8,\"Type\":\"pedestrian\"}]}','{\"SignalGroups\":[{\"SignalGroupId\":1,\"Phase\":1,\"Type\":\"vehicle\"},{\"SignalGroupId\":2,\"Phase\":2,\"Type\":\"vehicle\"},{\"SignalGroupId\":3,\"Phase\":3,\"Type\":\"vehicle\"},{\"SignalGroupId\":4,\"Phase\":4,\"Type\":\"vehicle\"},{\"SignalGroupId\":5,\"Phase\":5,\"Type\":\"vehicle\"},{\"SignalGroupId\":6,\"Phase\":6,\"Type\":\"vehicle\"},{\"SignalGroupId\":7,\"Phase\":7,\"Type\":\"vehicle\"},{\"SignalGroupId\":8,\"Phase\":8,\"Type\":\"vehicle\"},{\"SignalGroupId\":22,\"Phase\":2,\"Type\":\"pedestrian\"},{\"SignalGroupId\":24,\"Phase\":4,\"Type\":\"pedestrian\"},{\"SignalGroupId\":26,\"Phase\":6,\"Type\":\"pedestrian\"},{\"SignalGroupId\":28,\"Phase\":8,\"Type\":\"pedestrian\"}]}','JSON data defining a list of SignalGroups and phases.'),(55,10,'Local_IP','','','The IPv4 address of the local computer for receiving Traffic Signal Controller Broadcast Messages.'),(56,10,'Local_UDP_Port','local port','local port','The local UDP port for reception of Traffic Signal Controller Broadcast Messages from the TSC.'),(57,10,'TSC_IP','','','The IPv4 address of the destination Traffic Signal Controller (TSC).'),(58,10,'TSC_Remote_SNMP_Port','','','The destination port on the Traffic Signal Controller (TSC) for SNMP NTCIP communication.'),(59,11,'Instance','0','0','The instance of Preemption plugin.'),(60,11,'BasePreemptionOid','.1.3.6.1.4.1.1206.4.2.1.6.3.1.2.','.1.3.6.1.4.1.1206.4.2.1.6.3.1.2.','The BasePreemptionOid of Preemption plugin.'),(61,11,'ipwithport',':',':','The ipwithport of Preemption plugin.'),(62,11,'snmp_community','public','public','The snmp_community of Preemption plugin.'),(63,11,'map_path','/geo.json','/geo.json','The map_path for Preemption plugin.'),(64,11,'allowedList','{\"validVehicles\":[\"292710445\",\"123456789\",\"2345678\"]}','{\"validVehicles\":[\"292710445\",\"123456789\",\"2345678\"]}','List of vehicles BSM id that are allowed'),(65,12,'File Size In MB','100','100','Maximum size of the SPaT log file in mb.'),(66,12,'Filename','spatTx','spatTx','Default name of the SPaT log file.'),(67,12,'File Location','/var/log/tmx','/var/log/tmx','The location where the log files are stored. DO NOT edit while using docker deployment of V2X-Hub!'),(68,13,'File Size In MB','100','100','Maximum size of the BSM log file in mb.'),(69,13,'Filename','bsmTx','bsmTx','Default name of the BSM log file.'),(70,13,'File Location','/var/log/tmx','/var/log/tmx','The location where the log files are stored. DO NOT edit while using docker deployment of V2X-Hub!'),(71,14,'Frequency','1000','1000','The frequency to send the PSM in milliseconds.'),(72,14,'Instance','0','0','The instance of Pedestrian plugin.'),(73,14,'WebServiceIP','127.0.0.1','127.0.0.1','IP address at which the web service exists'),(74,14,'WebServicePort','9000','9000','Port at which Web service exists'),(75,15,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(76,15,'MapFile','/var/www/plugins/MAP/IVP_GF_TIM.xml','/var/www/plugins/MAP/IVP_GF_TIM.xml',''),(77,15,'Start_Broadcast_Date','01-01-2019','01-01-2019','The Start Broadcast Date for the TIM message in the (mm-dd-YYYY) format.'),(78,15,'Stop_Broadcast_Date','12-31-2020','12-31-2020','The Stop Broadcast Date for the TIM message in the (mm-dd-YYYY) format.'),(79,15,'Start_Broadcast_Time','06:00:00','06:00:00','The Start Broadcast Time for the TIM message in the (HH:MM:SS) format.'),(80,15,'Stop_Broadcast_Time','21:00:00','21:00:00','The Start Broadcast Time for the TIM message in the (HH:MM:SS) format.'),(81,15,'WebServiceIP','127.0.0.1','127.0.0.1','IP address at which the web service exists'),(82,15,'WebServicePort','10000','10000','Port at which Web service exists'),(83,16,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(84,16,'Instance','0','0','The instance of this plugin.'),(85,16,'WebServiceIP','127.0.0.1','127.0.0.1','Server IP address for V2X hub'),(86,16,'WebServicePort','22222','22222','Server Port for V2X hub'),(87,17,'...','...','...','...'),(88,18,'instance','1','1','instance of the application'),(89,18,'schedule_frequency','1','1','sample of incoming messages to forward, 1 = forwards every message'),(90,18,'ForwardMSG','1','1','Enable Forwarding of BSM'),(91,18,'BSMKafkaTopic','topic.OdeRawEncodedBSMJson','topic.OdeRawEncodedBSMJson','(Cond: ForwardMSG == True) Topic to use for forwarding BSM'),(92,18,'SPaTKafkaTopic','topic.OdeRawEncodedSPATJson','topic.OdeRawEncodedSPATJson','(Cond: ForwardMSG == True) Topic to use for forwarding BSM'),(93,18,'KafkaBrokerIp','172.31.55.238','172.31.55.238','IP address to be used for KAFKA broker'),(94,18,'KafkaBrokerPort','9092','9092','Port number to be used for KAFKA broker'); +INSERT INTO `pluginConfigurationParameter` VALUES (1,1,'SleepMS','100','100','The length of milliseconds to sleep between processing all messages.'),(2,1,'SSLEnabled','true','true','Enable secure connection using SSL.'),(3,1,'SSLPath','/var/www/plugins/.ssl','/var/www/plugins/.ssl','The path to the directory containing the SSL key and certificate files.'),(4,1,'EventRowLimit','50','50','The maximum number of rows returned for the initial Event Log query.'),(5,1,'DownloadPath','/var/www/download','/var/www/download','The path to the directory where downloaded files will be saved.'),(6,1,'LogLevel','ERROR','ERROR','The log level for this plugin'),(7,2,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(8,2,'MapFile','IVP_GF_CSW.xml','IVP_GF_CSW.xml',''),(9,2,'Snap Interval','300','300','The interval in milliseconds to keep a vehicle within a zone before allowing it to transition out of all zones.'),(10,2,'Vehicle Timeout','2000','2000','Timeout in milliseconds when a vehicle is removed from all zones if a BSM has not been received.'),(11,3,'DMS IP Address','192.168.25.30','192.168.25.30','The IP address of the NTCIP Dynamic Message Sign.'),(12,3,'DMS Port','9090','9090','The port of the NTCIP Dynamic Message Sign.'),(13,3,'Enable DMS','True','True','If true all messages are sent to the Dynamic Message Sign using NTCIP 1203.'),(14,3,'Enable Sign Simulator','True','True','If true all messages are sent to the Sign Simulator using UDP.'),(15,3,'Force Message ID','-1','-1','Immediately activates the message ID specified, then resets back to -1.'),(16,3,'Message 01','','','The text to display on the sign for ID 01 with any formatting (see NTCIP 1203).'),(17,3,'Message 02','[jl3][pt15o0]25[np]MPH','[jl3][pt15o0]25[np]MPH','The text to display on the sign for ID 02 with any formatting (see NTCIP 1203).'),(18,3,'Message 03','[jl3][pt15o0]SLOW[np]DOWN','[jl3][pt15o0]SLOW[np]DOWN','The text to display on the sign for ID 03 with any formatting (see NTCIP 1203).'),(19,3,'Message 04','[jl3][pt15o0]CRVE[np]AHED','[jl3][pt15o0]CRVE[np]AHED','The text to display on the sign for ID 04 with any formatting (see NTCIP 1203).'),(20,3,'Sign Sim IP Address','192.168.25.31','192.168.25.31','The IP address of the Sign Simulator that is the receipient of UDP messages.'),(21,3,'Sign Sim Port','9090','9090','The UDP port of the Sign Simulator that is the receipient of UDP messages.'),(22,4,'Messages_Destination_1','{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"PSM\", \"SendType\": \"PSM\", \"PSID\": \"0x8002\" } ,{ \"TmxType\": \"TMSG07\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\" }] }','{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"PSM\", \"SendType\": \"PSM\", \"PSID\": \"0x8002\" } ,{ \"TmxType\": \"TMSG07\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\" }] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 1.'),(23,4,'Messages_Destination_2','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 2.'),(24,4,'Messages_Destination_3','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 3.'),(25,4,'Messages_Destination_4','{ \"Messages\": [ ] }','{ \"Messages\": [ ] }','JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 4.'),(26,4,'Destination_1','127.0.0.1:1516','127.0.0.1:1516','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_1.'),(27,4,'Destination_2','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_2.'),(28,4,'Destination_3','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_3.'),(29,4,'Destination_4','0','0','The destination UDP server(s) and port number(s) on the DSRC radio for all messages specified by Messages_Destination_4.'),(30,4,'Signature','False','False','True or False value indicating whether to sign the messages.'),(31,5,'Frequency','500','500','Rate to send Location Message in milliseconds'),(32,5,'LatchHeadingSpeed','2.5','2.5','Speed at which the heading parameter should be latched, in mph. Set to 0 to disable latching.'),(33,5,'GPSSource','localhost','localhost','Host where the GPSd is running'),(34,5,'SendRawNMEA','true','true','Route the raw NMEA strings from GPSd through TMX'),(35,6,'Frequency','1000','1000','The frequency to send the MAP message in milliseconds.'),(36,6,'MAP_Files','{ \"MapFiles\": [\n {\"Action\":0, \"FilePath\":\"GID_Telegraph-Twelve_Mile_withEgress.xml\"}\n] }','{ \"MapFiles\": [\n {\"Action\":0, \"FilePath\":\"GID_Telegraph-Twelve_Mile_withEgress.xml\"}\n] }','JSON data defining a list of map files. One map file for each action set specified by the TSC.'),(37,7,'IP','127.0.0.1','127.0.0.1','IP address for the incoming message network connection.'),(38,7,'Port','26789','26789','Port for the incoming message network connection.'),(39,7,'RouteDSRC','false','false','Set the flag to route a received J2735 message over DSRC.'),(40,7,'EnableSimulatedBSM','true','true','Accept and route incoming BSM messages from a V2I Hub simulator.'),(41,7,'EnableSimulatedSRM','true','true','Accept and route incoming SRM messages from a V2I Hub simulator.'),(42,7,'EnableSimulatedLocation','true','true','Accept and route incoming GPS location messages from a V2I Hub simulator.'),(43,8,'ODEIP','127.0.0.1','127.0.0.1','IP address for the ODE network connection.'),(44,8,'ODEPort','26789','26789','Port for the ODE network connection.'),(45,9,'Endpoint IP','156.63.133.118','156.63.133.118','NTRIP caster endpoint IP address'),(46,9,'Endpoint Port','2101','2101','NTRIP caster endpoint port'),(47,9,'Username','username','username','NTRIP caster authentication username'),(48,9,'Password','password','password','NTRIP caster authentication password'),(49,9,'Mountpoint','ODOT_RTCM23','ODOT_RTCM23','NTRIP caster mountpoint'),(50,9,'RTCM Version','Unknown','Unknown','Specify the expected RTCM message version (2.3 or 3.3) coming from the caster. Use Unknown to auto detect the version, which is done using trial and error, thus may be slow.'),(51,9,'Route RTCM','false','false','Route the RTCM messages created from NTRIP internally for use by other plugins.'),(52,10,'Intersection_Id','1','1','The intersection id for SPAT generated by this plugin.'),(53,10,'Intersection_Name','Intersection','Intersection','The intersection name for SPAT generated by this plugin.'),(54,10,'SignalGroupMapping','{\"SignalGroups\":[{\"SignalGroupId\":1,\"Phase\":1,\"Type\":\"vehicle\"},{\"SignalGroupId\":2,\"Phase\":2,\"Type\":\"vehicle\"},{\"SignalGroupId\":3,\"Phase\":3,\"Type\":\"vehicle\"},{\"SignalGroupId\":4,\"Phase\":4,\"Type\":\"vehicle\"},{\"SignalGroupId\":5,\"Phase\":5,\"Type\":\"vehicle\"},{\"SignalGroupId\":6,\"Phase\":6,\"Type\":\"vehicle\"},{\"SignalGroupId\":7,\"Phase\":7,\"Type\":\"vehicle\"},{\"SignalGroupId\":8,\"Phase\":8,\"Type\":\"vehicle\"},{\"SignalGroupId\":22,\"Phase\":2,\"Type\":\"pedestrian\"},{\"SignalGroupId\":24,\"Phase\":4,\"Type\":\"pedestrian\"},{\"SignalGroupId\":26,\"Phase\":6,\"Type\":\"pedestrian\"},{\"SignalGroupId\":28,\"Phase\":8,\"Type\":\"pedestrian\"}]}','{\"SignalGroups\":[{\"SignalGroupId\":1,\"Phase\":1,\"Type\":\"vehicle\"},{\"SignalGroupId\":2,\"Phase\":2,\"Type\":\"vehicle\"},{\"SignalGroupId\":3,\"Phase\":3,\"Type\":\"vehicle\"},{\"SignalGroupId\":4,\"Phase\":4,\"Type\":\"vehicle\"},{\"SignalGroupId\":5,\"Phase\":5,\"Type\":\"vehicle\"},{\"SignalGroupId\":6,\"Phase\":6,\"Type\":\"vehicle\"},{\"SignalGroupId\":7,\"Phase\":7,\"Type\":\"vehicle\"},{\"SignalGroupId\":8,\"Phase\":8,\"Type\":\"vehicle\"},{\"SignalGroupId\":22,\"Phase\":2,\"Type\":\"pedestrian\"},{\"SignalGroupId\":24,\"Phase\":4,\"Type\":\"pedestrian\"},{\"SignalGroupId\":26,\"Phase\":6,\"Type\":\"pedestrian\"},{\"SignalGroupId\":28,\"Phase\":8,\"Type\":\"pedestrian\"}]}','JSON data defining a list of SignalGroups and phases.'),(55,10,'Local_IP','','','The IPv4 address of the local computer for receiving Traffic Signal Controller Broadcast Messages.'),(56,10,'Local_UDP_Port','local port','local port','The local UDP port for reception of Traffic Signal Controller Broadcast Messages from the TSC.'),(57,10,'TSC_IP','','','The IPv4 address of the destination Traffic Signal Controller (TSC).'),(58,10,'TSC_Remote_SNMP_Port','','','The destination port on the Traffic Signal Controller (TSC) for SNMP NTCIP communication.'),(59,11,'Instance','0','0','The instance of Preemption plugin.'),(60,11,'BasePreemptionOid','.1.3.6.1.4.1.1206.4.2.1.6.3.1.2.','.1.3.6.1.4.1.1206.4.2.1.6.3.1.2.','The BasePreemptionOid of Preemption plugin.'),(61,11,'ipwithport',':',':','The ipwithport of Preemption plugin.'),(62,11,'snmp_community','public','public','The snmp_community of Preemption plugin.'),(63,11,'map_path','/geo.json','/geo.json','The map_path for Preemption plugin.'),(64,11,'allowedList','{\"validVehicles\":[\"292710445\",\"123456789\",\"2345678\"]}','{\"validVehicles\":[\"292710445\",\"123456789\",\"2345678\"]}','List of vehicles BSM id that are allowed'),(65,12,'File Size In MB','100','100','Maximum size of the SPaT log file in mb.'),(66,12,'Filename','spatTx','spatTx','Default name of the SPaT log file.'),(67,12,'File Location','/var/log/tmx','/var/log/tmx','The location where the log files are stored. DO NOT edit while using docker deployment of V2X-Hub!'),(68,13,'File Size In MB','100','100','Maximum size of the BSM log file in mb.'),(69,13,'Filename','bsmTx','bsmTx','Default name of the BSM log file.'),(70,13,'File Location','/var/log/tmx','/var/log/tmx','The location where the log files are stored. DO NOT edit while using docker deployment of V2X-Hub!'),(71,14,'Frequency','1000','1000','The frequency to send the PSM in milliseconds.'),(72,14,'Instance','0','0','The instance of Pedestrian plugin.'),(73,14,'WebServiceIP','127.0.0.1','127.0.0.1','IP address at which the web service exists'),(74,14,'WebServicePort','9000','9000','Port at which Web service exists'),(75,15,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(76,15,'MapFile','/var/www/plugins/MAP/IVP_GF_TIM.xml','/var/www/plugins/MAP/IVP_GF_TIM.xml',''),(77,15,'Start_Broadcast_Date','01-01-2019','01-01-2019','The Start Broadcast Date for the TIM message in the (mm-dd-YYYY) format.'),(78,15,'Stop_Broadcast_Date','12-31-2020','12-31-2020','The Stop Broadcast Date for the TIM message in the (mm-dd-YYYY) format.'),(79,15,'Start_Broadcast_Time','06:00:00','06:00:00','The Start Broadcast Time for the TIM message in the (HH:MM:SS) format.'),(80,15,'Stop_Broadcast_Time','21:00:00','21:00:00','The Start Broadcast Time for the TIM message in the (HH:MM:SS) format.'),(81,15,'WebServiceIP','127.0.0.1','127.0.0.1','IP address at which the web service exists'),(82,15,'WebServicePort','10000','10000','Port at which Web service exists'),(83,16,'Frequency','1000','1000','The frequency to send the TIM in milliseconds.'),(84,16,'Instance','0','0','The instance of this plugin.'),(85,16,'WebServiceIP','127.0.0.1','127.0.0.1','Server IP address for V2X hub'),(86,16,'WebServicePort','22222','22222','Server Port for V2X hub'),(87,17,'Database_IP','127.0.0.1','127.0.0.1','IP address of database'),(88,17,'Database_Port','3306','3306','Port of database'),(89,17,'Database_Username','root','root','Username for database'),(90,17,'Database_Password','ivp','ivp','Password for database'),(91,17,'Database_Name','PORT_DRAYAGE','PORT_DRAYAGE','Name of database'),(92,17,'LogLevel','INFO','INFO','The log level for this plugin'),(93,18,'instance','1','1','instance of the application'),(94,18,'schedule_frequency','1','1','sample of incoming messages to forward, 1 = forwards every message'),(95,18,'ForwardMSG','1','1','Enable Forwarding of BSM'),(96,18,'BSMKafkaTopic','topic.OdeRawEncodedBSMJson','topic.OdeRawEncodedBSMJson','(Cond: ForwardMSG == True) Topic to use for forwarding BSM'),(97,18,'SPaTKafkaTopic','topic.OdeRawEncodedSPATJson','topic.OdeRawEncodedSPATJson','(Cond: ForwardMSG == True) Topic to use for forwarding BSM'),(98,18,'KafkaBrokerIp','172.31.55.238','172.31.55.238','IP address to be used for KAFKA broker'),(99,18,'KafkaBrokerPort','9092','9092','Port number to be used for KAFKA broker'),(100,19,'Startup Delay (ms)','10000','10000','Delay in milliseconds before starting any plugins.'),(101,19,'Monitor Check Interval (ms)','5000','5000','Delay in milliseconds between monitor checks.'),(102,19,'Max Startup Time (ms)','15000','15000','Maximum allowed startup time of a plugin before it is rebooted.'),(103,20,'Database Refresh Interval (ms)','2000','2000','The interval (in milliseconds) between uploads of message statistics to the database.'),(104,20,'Message Averaging Window (ms)','20000','20000','The averaging window (in milliseconds) that the profiler measures average interval.'),(105,21,'Purge Intervals (sec)','120','120','Interval between purges of history items'),(106,21,'Max Event Log Size','2000','2000','Maximum number of event log entries to keep. A value of zero will result in no purging of event log entries'); /*!40000 ALTER TABLE `pluginConfigurationParameter` ENABLE KEYS */; UNLOCK TABLES; @@ -247,7 +247,7 @@ CREATE TABLE `pluginMessageMap` ( KEY `messageTypeId` (`messageTypeId`), CONSTRAINT `pluginMessageMap_ibfk_1` FOREIGN KEY (`pluginId`) REFERENCES `plugin` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `pluginMessageMap_ibfk_2` FOREIGN KEY (`messageTypeId`) REFERENCES `messageType` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB AUTO_INCREMENT=1362 DEFAULT CHARSET=latin1 COMMENT='This table identifies the types of messages generated by each plugin.'; +) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=latin1 COMMENT='This table identifies the types of messages generated by each plugin.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -256,7 +256,7 @@ CREATE TABLE `pluginMessageMap` ( LOCK TABLES `pluginMessageMap` WRITE; /*!40000 ALTER TABLE `pluginMessageMap` DISABLE KEYS */; -INSERT INTO `pluginMessageMap` VALUES (1,1,15),(1361,7,1),(70,7,15),(75,13,15); +INSERT INTO `pluginMessageMap` VALUES (1,1,15),(1361,7,1),(70,7,15),(75,13,15),(1538,15,14),(1435,17,30); /*!40000 ALTER TABLE `pluginMessageMap` ENABLE KEYS */; UNLOCK TABLES; @@ -276,7 +276,7 @@ CREATE TABLE `pluginStatus` ( UNIQUE KEY `UQ_pluginId_key` (`pluginId`,`key`), KEY `pluginId` (`pluginId`), CONSTRAINT `pluginStatus_ibfk_2` FOREIGN KEY (`pluginId`) REFERENCES `plugin` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=latin1; +) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -302,7 +302,7 @@ CREATE TABLE `systemConfigurationParameter` ( `defaultValue` text NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `key` (`key`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 COMMENT='This table lists the IVP system configuration parameters used by both core components and plugins to control the behavior of the system.'; +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 COMMENT='This table lists the IVP system configuration parameters used by both core components and plugins to control the behavior of the system.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -330,7 +330,7 @@ CREATE TABLE `user` ( PRIMARY KEY (`id`), UNIQUE KEY `UQ_user_id` (`id`), UNIQUE KEY `UQ_user_username` (`username`) -) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 COMMENT='The list of accounts that can access the IVP platform via the administrative portal is held in the users table.'; +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1 COMMENT='The list of accounts that can access the IVP platform via the administrative portal is held in the users table.'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -351,4 +351,4 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2021-06-23 23:52:23 +-- Dump completed on 2021-08-25 13:36:29 diff --git a/configuration/arm64/mysql/port_drayage.sql b/configuration/arm64/mysql/port_drayage.sql new file mode 100644 index 000000000..71c93e51f --- /dev/null +++ b/configuration/arm64/mysql/port_drayage.sql @@ -0,0 +1,91 @@ +-- MySQL dump 10.13 Distrib 5.7.34, for Linux (x86_64) +-- +-- Host: 127.0.0.1 Database: PORT_DRAYAGE +-- ------------------------------------------------------ +-- Server version 5.7.35 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `PORT_DRAYAGE` +-- + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `PORT_DRAYAGE` /*!40100 DEFAULT CHARACTER SET latin1 */; + +USE `PORT_DRAYAGE`; + +-- +-- Table structure for table `first_action` +-- + +DROP TABLE IF EXISTS `first_action`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `first_action` ( + `cmv_id` int(4) NOT NULL, + `cargo_id` varchar(20) DEFAULT NULL, + `destination_lat` decimal(9,7) NOT NULL, + `destination_long` decimal(9,7) NOT NULL, + `operation` varchar(20) NOT NULL, + `action_id` varchar(36) NOT NULL, + `next_action` varchar(36) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `first_action` +-- + +LOCK TABLES `first_action` WRITE; +/*!40000 ALTER TABLE `first_action` DISABLE KEYS */; +INSERT INTO `first_action` VALUES (123,'SOME_CARGO',38.9548890,-77.1481430,'PICKUP','4bea1c45-e421-11eb-a8cc-000c29ae389d','32320c8a-e422-11eb-a8cc-000c29ae389d'); +/*!40000 ALTER TABLE `first_action` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `freight` +-- + +DROP TABLE IF EXISTS `freight`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `freight` ( + `cmv_id` int(4) NOT NULL, + `cargo_id` varchar(20) DEFAULT NULL, + `destination_lat` decimal(9,7) NOT NULL, + `destination_long` decimal(9,7) NOT NULL, + `operation` varchar(20) NOT NULL, + `action_id` varchar(36) NOT NULL, + `next_action` varchar(36) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `freight` +-- + +LOCK TABLES `freight` WRITE; +/*!40000 ALTER TABLE `freight` DISABLE KEYS */; +INSERT INTO `freight` VALUES (123,NULL,38.9549780,-77.1475790,'EXIT_STAGING_AREA','32320c8a-e422-11eb-a8cc-000c29ae389d','4ace39e6-ee36-11eb-9a03-0242ac130003'),(123,'SOME_CARGO',38.9548890,-77.1481430,'PICKUP','4bea1c45-e421-11eb-a8cc-000c29ae389d','32320c8a-e422-11eb-a8cc-000c29ae389d'); +/*!40000 ALTER TABLE `freight` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2021-07-21 11:42:55 diff --git a/container/service.sh b/container/service.sh index 808754dad..ad8da583b 100755 --- a/container/service.sh +++ b/container/service.sh @@ -19,8 +19,8 @@ tmxctl --plugin-install MessageLoggerPlugin.zip tmxctl --plugin-install PedestrianPlugin.zip tmxctl --plugin-install TimPlugin.zip tmxctl --plugin-install CARMACloudPlugin.zip -tmxctl --plugin-install MobilityOperationPlugin.zip tmxctl --plugin-install ODELoggerPlugin.zip +tmxctl --plugin-install PortDrayagePlugin.zip tmxctl --plugin CommandPlugin --enable /usr/local/bin/tmxcore diff --git a/docker/Dockerfile-depl b/docker/Dockerfile-depl index caeae84a1..6be0a8170 100644 --- a/docker/Dockerfile-depl +++ b/docker/Dockerfile-depl @@ -70,9 +70,11 @@ RUN cmake . RUN make RUN make install WORKDIR /home/V2X-Hub/ext/ccserver -RUN rm -rf /home/V2X-Hub/ext/ - +WORKDIR /home/V2X-Hub/ext/pdclient +RUN cmake . +RUN make +RUN make install WORKDIR /home/V2X-Hub/src/v2i-hub/ RUN cmake . -DqserverPedestrian_DIR=/usr/local/share/qserverPedestrian/cmake -Dv2xhubWebAPI_DIR=/usr/local/share/v2xhubWebAPI/cmake/ @@ -110,8 +112,10 @@ RUN ln -s ../bin TimPlugin/bin RUN zip TimPlugin.zip TimPlugin/bin/TimPlugin TimPlugin/manifest.json RUN ln -s ../bin CARMACloudPlugin/bin RUN zip CARMACloudPlugin.zip CARMACloudPlugin/bin/CARMACloudPlugin CARMACloudPlugin/manifest.json -RUN ln -s ../bin MobilityOperationPlugin/bin -RUN zip MobilityOperationPlugin.zip MobilityOperationPlugin/bin/MobilityOperationPlugin MobilityOperationPlugin/manifest.json + +RUN ln -s ../bin PortDrayagePlugin/bin +RUN zip PortDrayagePlugin.zip PortDrayagePlugin/bin/PortDrayagePlugin PortDrayagePlugin/manifest.json + RUN ln -s ../bin ODELoggerPlugin/bin RUN zip ODELoggerPlugin.zip ODELoggerPlugin/bin/ODELoggerPlugin ODELoggerPlugin/manifest.json diff --git a/docs/Release_notes.md b/docs/Release_notes.md index b152d4861..f96643126 100644 --- a/docs/Release_notes.md +++ b/docs/Release_notes.md @@ -1,6 +1,41 @@ V2X-Hub Release Notes ---------------------------- +Version 6.3, released Dec 17th, 2021 +-------------------------------------------------------- + +**Summary:** +V2X Hub release version 6.3 is a hotfix release for 6.0. + +Enhancements in this release: +- Issue 290: Implemented several UI changes to the Port Drayage Web Service for CARMA-Freight as below. +1. Added landing page with CARMA-Streets Logo and Description +2. Added Tab Icons and tab notifications +3. Added Footer with FHWA and MARAD logos +4. Added indication of operation area (PORT or STAGING) + +Fixes in this release: +- Issue 287: Updated image tags for arm64 and amd64 Docker-compose deployments to use 6.2 release images instead of release candidate images. + +Version 6.2, released Dec 10th, 2021 +-------------------------------------------------------- + +**Summary:** +V2X Hub release version 6.2 is a hotfix release for 6.0. + +Enhancements in this release: +- Issue 268: Added Spring Boot Port Drayage Web Service which includes Open API, REST API and Implemented Spring boot REST server. Added Maven pom.xml for Open API Spring boot server code generation. Updated Maven pom.xml for unit test and Jacoco unit test coverage report. +- Issue 255: Created Lightweight V2X-Hub Deployment Image by removing unnecessary apt-get tools and libraries installed and unnecessary files included in build context and any steps not necessary for V2X-Hub deployment. +- Issue 272: Added REST Client to Port Drayage Plugin. Changes consist of Qt REST ext/pdclient library generated using Open API code gen and added logic to request and poll loading/unloading and inspection actions from web service, and added Port Drayage Plugin in sonar scanner properties. +- Issue 279&281: Implementing Port Drayage Plugin CI/CD integration by Adding Docker file, Circle CI build and Push workflow and Docker-compose setup for Port Drayage Web service and updated DSRC Immediate Forward Plugin Configurations to include Mobility Operation message by default. +- Issue 282: Added Clear button for web service to clear existing actions to allow for repeated executions of the same sequence of actions without requiring restart of web service. + +Fixes in this release: +- Issue 213: Fixed PLOG and FILE_LOG logic where PLOG never prints statements and FILE_LOG only prints error level statements. Discovered and fixed some segmentation faults in Qt HTTP client code and Tmxctl CLI calls to obtain correct MySQL credentials. +- Issue 257: Fixed DB Connection Pool Logging to debug the Docker secrets deployment implementation was unintentionally kept in V2X-Hub which cause V2X-Hub to print the MySQL password it uses every time it attempts to authenticate to MySQL. +- Issue 260: Fixed Sonar scan issues found in Preemption Plugin during V2xhub sonar scanning. +- Issue 280: Fixed the mobility operation messages used for Vehicle and Infrastructure communication does not indicate the origin of the message where infrastructure may attempt to respond to other infrastructure communication. + Version 6.1, released Oct 15th, 2021 -------------------------------------------------------- diff --git a/ext/pdclient/CMakeLists.txt b/ext/pdclient/CMakeLists.txt new file mode 100644 index 000000000..562b24523 --- /dev/null +++ b/ext/pdclient/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.2) + +project(pdclient) +set(CMAKE_VERBOSE_MAKEFILE ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_AUTOMOC ON) + +if (MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") +else () + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wno-unused-variable") +endif () + +find_package(Qt5Core REQUIRED) +find_package(Qt5Network REQUIRED) + +add_library(${PROJECT_NAME} + OAIActionStatusList.cpp + OAIContainerActionStatus.cpp + OAIContainerRequest.cpp + OAIInspectionRequest.cpp + OAIInspectionStatus.cpp + OAIInspectionStatusList.cpp + OAIDefaultApi.cpp + OAIHelpers.cpp + OAIHttpRequest.cpp + OAIHttpFileElement.cpp +) +target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Network ) + +if(NOT APPLE) + target_link_libraries(${PROJECT_NAME} PRIVATE ssl crypto) +endif() + +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14) +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_EXTENSIONS OFF) + +install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) + +FILE(GLOB files "${CMAKE_CURRENT_SOURCE_DIR}/*.h") +INSTALL(FILES ${files} DESTINATION /usr/local/include/${PROJECT_NAME} ) diff --git a/ext/pdclient/OAIActionStatusList.cpp b/ext/pdclient/OAIActionStatusList.cpp new file mode 100644 index 000000000..eff61e965 --- /dev/null +++ b/ext/pdclient/OAIActionStatusList.cpp @@ -0,0 +1,100 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#include "OAIActionStatusList.h" + +#include +#include +#include +#include + +#include "OAIHelpers.h" + +namespace OpenAPI { + +OAIActionStatusList::OAIActionStatusList(QString json) { + this->initializeModel(); + this->fromJson(json); +} + +OAIActionStatusList::OAIActionStatusList() { + this->initializeModel(); +} + +OAIActionStatusList::~OAIActionStatusList() {} + +void OAIActionStatusList::initializeModel() { + + m_actions_isSet = false; + m_actions_isValid = false; +} + +void OAIActionStatusList::fromJson(QString jsonString) { + QByteArray array(jsonString.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); +} + +void OAIActionStatusList::fromJsonObject(QJsonObject json) { + + m_actions_isValid = ::OpenAPI::fromJsonValue(actions, json[QString("actions")]); + m_actions_isSet = !json[QString("actions")].isNull() && m_actions_isValid; +} + +QString OAIActionStatusList::asJson() const { + QJsonObject obj = this->asJsonObject(); + QJsonDocument doc(obj); + QByteArray bytes = doc.toJson(); + return QString(bytes); +} + +QJsonObject OAIActionStatusList::asJsonObject() const { + QJsonObject obj; + if (actions.size() > 0) { + obj.insert(QString("actions"), ::OpenAPI::toJsonValue(actions)); + } + return obj; +} + +QList OAIActionStatusList::getActions() const { + return actions; +} +void OAIActionStatusList::setActions(const QList &actions) { + this->actions = actions; + this->m_actions_isSet = true; +} + +bool OAIActionStatusList::is_actions_Set() const{ + return m_actions_isSet; +} + +bool OAIActionStatusList::is_actions_Valid() const{ + return m_actions_isValid; +} + +bool OAIActionStatusList::isSet() const { + bool isObjectUpdated = false; + do { + if (actions.size() > 0) { + isObjectUpdated = true; + break; + } + } while (false); + return isObjectUpdated; +} + +bool OAIActionStatusList::isValid() const { + // only required properties are required for the object to be considered valid + return true; +} + +} // namespace OpenAPI diff --git a/ext/pdclient/OAIActionStatusList.h b/ext/pdclient/OAIActionStatusList.h new file mode 100644 index 000000000..2447f1cfa --- /dev/null +++ b/ext/pdclient/OAIActionStatusList.h @@ -0,0 +1,62 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * OAIActionStatusList.h + * + * + */ + +#ifndef OAIActionStatusList_H +#define OAIActionStatusList_H + +#include + +#include "OAIContainerActionStatus.h" +#include + +#include "OAIEnum.h" +#include "OAIObject.h" + +namespace OpenAPI { + +class OAIActionStatusList : public OAIObject { +public: + OAIActionStatusList(); + OAIActionStatusList(QString json); + ~OAIActionStatusList() override; + + QString asJson() const override; + QJsonObject asJsonObject() const override; + void fromJsonObject(QJsonObject json) override; + void fromJson(QString jsonString) override; + + QList getActions() const; + void setActions(const QList &actions); + bool is_actions_Set() const; + bool is_actions_Valid() const; + + virtual bool isSet() const override; + virtual bool isValid() const override; + +private: + void initializeModel(); + + QList actions; + bool m_actions_isSet; + bool m_actions_isValid; +}; + +} // namespace OpenAPI + +Q_DECLARE_METATYPE(OpenAPI::OAIActionStatusList) + +#endif // OAIActionStatusList_H diff --git a/ext/pdclient/OAIContainerActionStatus.cpp b/ext/pdclient/OAIContainerActionStatus.cpp new file mode 100644 index 000000000..6b7f2a3a3 --- /dev/null +++ b/ext/pdclient/OAIContainerActionStatus.cpp @@ -0,0 +1,250 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#include "OAIContainerActionStatus.h" + +#include +#include +#include +#include + +#include "OAIHelpers.h" + +namespace OpenAPI { + +OAIContainerActionStatus::OAIContainerActionStatus(QString json) { + this->initializeModel(); + this->fromJson(json); +} + +OAIContainerActionStatus::OAIContainerActionStatus() { + this->initializeModel(); +} + +OAIContainerActionStatus::~OAIContainerActionStatus() {} + +void OAIContainerActionStatus::initializeModel() { + + m_vehicle_id_isSet = false; + m_vehicle_id_isValid = false; + + m_container_id_isSet = false; + m_container_id_isValid = false; + + m_action_id_isSet = false; + m_action_id_isValid = false; + + m_status_isSet = false; + m_status_isValid = false; + + m_requested_isSet = false; + m_requested_isValid = false; + + m_completed_isSet = false; + m_completed_isValid = false; +} + +void OAIContainerActionStatus::fromJson(QString jsonString) { + QByteArray array(jsonString.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); +} + +void OAIContainerActionStatus::fromJsonObject(QJsonObject json) { + + m_vehicle_id_isValid = ::OpenAPI::fromJsonValue(vehicle_id, json[QString("vehicle_id")]); + m_vehicle_id_isSet = !json[QString("vehicle_id")].isNull() && m_vehicle_id_isValid; + + m_container_id_isValid = ::OpenAPI::fromJsonValue(container_id, json[QString("container_id")]); + m_container_id_isSet = !json[QString("container_id")].isNull() && m_container_id_isValid; + + m_action_id_isValid = ::OpenAPI::fromJsonValue(action_id, json[QString("action_id")]); + m_action_id_isSet = !json[QString("action_id")].isNull() && m_action_id_isValid; + + m_status_isValid = ::OpenAPI::fromJsonValue(status, json[QString("status")]); + m_status_isSet = !json[QString("status")].isNull() && m_status_isValid; + + m_requested_isValid = ::OpenAPI::fromJsonValue(requested, json[QString("requested")]); + m_requested_isSet = !json[QString("requested")].isNull() && m_requested_isValid; + + m_completed_isValid = ::OpenAPI::fromJsonValue(completed, json[QString("completed")]); + m_completed_isSet = !json[QString("completed")].isNull() && m_completed_isValid; +} + +QString OAIContainerActionStatus::asJson() const { + QJsonObject obj = this->asJsonObject(); + QJsonDocument doc(obj); + QByteArray bytes = doc.toJson(); + return QString(bytes); +} + +QJsonObject OAIContainerActionStatus::asJsonObject() const { + QJsonObject obj; + if (m_vehicle_id_isSet) { + obj.insert(QString("vehicle_id"), ::OpenAPI::toJsonValue(vehicle_id)); + } + if (m_container_id_isSet) { + obj.insert(QString("container_id"), ::OpenAPI::toJsonValue(container_id)); + } + if (m_action_id_isSet) { + obj.insert(QString("action_id"), ::OpenAPI::toJsonValue(action_id)); + } + if (m_status_isSet) { + obj.insert(QString("status"), ::OpenAPI::toJsonValue(status)); + } + if (m_requested_isSet) { + obj.insert(QString("requested"), ::OpenAPI::toJsonValue(requested)); + } + if (m_completed_isSet) { + obj.insert(QString("completed"), ::OpenAPI::toJsonValue(completed)); + } + return obj; +} + +QString OAIContainerActionStatus::getVehicleId() const { + return vehicle_id; +} +void OAIContainerActionStatus::setVehicleId(const QString &vehicle_id) { + this->vehicle_id = vehicle_id; + this->m_vehicle_id_isSet = true; +} + +bool OAIContainerActionStatus::is_vehicle_id_Set() const{ + return m_vehicle_id_isSet; +} + +bool OAIContainerActionStatus::is_vehicle_id_Valid() const{ + return m_vehicle_id_isValid; +} + +QString OAIContainerActionStatus::getContainerId() const { + return container_id; +} +void OAIContainerActionStatus::setContainerId(const QString &container_id) { + this->container_id = container_id; + this->m_container_id_isSet = true; +} + +bool OAIContainerActionStatus::is_container_id_Set() const{ + return m_container_id_isSet; +} + +bool OAIContainerActionStatus::is_container_id_Valid() const{ + return m_container_id_isValid; +} + +QString OAIContainerActionStatus::getActionId() const { + return action_id; +} +void OAIContainerActionStatus::setActionId(const QString &action_id) { + this->action_id = action_id; + this->m_action_id_isSet = true; +} + +bool OAIContainerActionStatus::is_action_id_Set() const{ + return m_action_id_isSet; +} + +bool OAIContainerActionStatus::is_action_id_Valid() const{ + return m_action_id_isValid; +} + +QString OAIContainerActionStatus::getStatus() const { + return status; +} +void OAIContainerActionStatus::setStatus(const QString &status) { + this->status = status; + this->m_status_isSet = true; +} + +bool OAIContainerActionStatus::is_status_Set() const{ + return m_status_isSet; +} + +bool OAIContainerActionStatus::is_status_Valid() const{ + return m_status_isValid; +} + +qint64 OAIContainerActionStatus::getRequested() const { + return requested; +} +void OAIContainerActionStatus::setRequested(const qint64 &requested) { + this->requested = requested; + this->m_requested_isSet = true; +} + +bool OAIContainerActionStatus::is_requested_Set() const{ + return m_requested_isSet; +} + +bool OAIContainerActionStatus::is_requested_Valid() const{ + return m_requested_isValid; +} + +qint64 OAIContainerActionStatus::getCompleted() const { + return completed; +} +void OAIContainerActionStatus::setCompleted(const qint64 &completed) { + this->completed = completed; + this->m_completed_isSet = true; +} + +bool OAIContainerActionStatus::is_completed_Set() const{ + return m_completed_isSet; +} + +bool OAIContainerActionStatus::is_completed_Valid() const{ + return m_completed_isValid; +} + +bool OAIContainerActionStatus::isSet() const { + bool isObjectUpdated = false; + do { + if (m_vehicle_id_isSet) { + isObjectUpdated = true; + break; + } + + if (m_container_id_isSet) { + isObjectUpdated = true; + break; + } + + if (m_action_id_isSet) { + isObjectUpdated = true; + break; + } + + if (m_status_isSet) { + isObjectUpdated = true; + break; + } + + if (m_requested_isSet) { + isObjectUpdated = true; + break; + } + + if (m_completed_isSet) { + isObjectUpdated = true; + break; + } + } while (false); + return isObjectUpdated; +} + +bool OAIContainerActionStatus::isValid() const { + // only required properties are required for the object to be considered valid + return m_vehicle_id_isValid && m_container_id_isValid && m_action_id_isValid && m_status_isValid && m_requested_isValid && true; +} + +} // namespace OpenAPI diff --git a/ext/pdclient/OAIContainerActionStatus.h b/ext/pdclient/OAIContainerActionStatus.h new file mode 100644 index 000000000..e117d287c --- /dev/null +++ b/ext/pdclient/OAIContainerActionStatus.h @@ -0,0 +1,106 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * OAIContainerActionStatus.h + * + * + */ + +#ifndef OAIContainerActionStatus_H +#define OAIContainerActionStatus_H + +#include + +#include + +#include "OAIEnum.h" +#include "OAIObject.h" + +namespace OpenAPI { + +class OAIContainerActionStatus : public OAIObject { +public: + OAIContainerActionStatus(); + OAIContainerActionStatus(QString json); + ~OAIContainerActionStatus() override; + + QString asJson() const override; + QJsonObject asJsonObject() const override; + void fromJsonObject(QJsonObject json) override; + void fromJson(QString jsonString) override; + + QString getVehicleId() const; + void setVehicleId(const QString &vehicle_id); + bool is_vehicle_id_Set() const; + bool is_vehicle_id_Valid() const; + + QString getContainerId() const; + void setContainerId(const QString &container_id); + bool is_container_id_Set() const; + bool is_container_id_Valid() const; + + QString getActionId() const; + void setActionId(const QString &action_id); + bool is_action_id_Set() const; + bool is_action_id_Valid() const; + + QString getStatus() const; + void setStatus(const QString &status); + bool is_status_Set() const; + bool is_status_Valid() const; + + qint64 getRequested() const; + void setRequested(const qint64 &requested); + bool is_requested_Set() const; + bool is_requested_Valid() const; + + qint64 getCompleted() const; + void setCompleted(const qint64 &completed); + bool is_completed_Set() const; + bool is_completed_Valid() const; + + virtual bool isSet() const override; + virtual bool isValid() const override; + +private: + void initializeModel(); + + QString vehicle_id; + bool m_vehicle_id_isSet; + bool m_vehicle_id_isValid; + + QString container_id; + bool m_container_id_isSet; + bool m_container_id_isValid; + + QString action_id; + bool m_action_id_isSet; + bool m_action_id_isValid; + + QString status; + bool m_status_isSet; + bool m_status_isValid; + + qint64 requested; + bool m_requested_isSet; + bool m_requested_isValid; + + qint64 completed; + bool m_completed_isSet; + bool m_completed_isValid; +}; + +} // namespace OpenAPI + +Q_DECLARE_METATYPE(OpenAPI::OAIContainerActionStatus) + +#endif // OAIContainerActionStatus_H diff --git a/ext/pdclient/OAIContainerRequest.cpp b/ext/pdclient/OAIContainerRequest.cpp new file mode 100644 index 000000000..616f75f7d --- /dev/null +++ b/ext/pdclient/OAIContainerRequest.cpp @@ -0,0 +1,160 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#include "OAIContainerRequest.h" + +#include +#include +#include +#include + +#include "OAIHelpers.h" + +namespace OpenAPI { + +OAIContainerRequest::OAIContainerRequest(QString json) { + this->initializeModel(); + this->fromJson(json); +} + +OAIContainerRequest::OAIContainerRequest() { + this->initializeModel(); +} + +OAIContainerRequest::~OAIContainerRequest() {} + +void OAIContainerRequest::initializeModel() { + + m_vehicle_id_isSet = false; + m_vehicle_id_isValid = false; + + m_container_id_isSet = false; + m_container_id_isValid = false; + + m_action_id_isSet = false; + m_action_id_isValid = false; +} + +void OAIContainerRequest::fromJson(QString jsonString) { + QByteArray array(jsonString.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); +} + +void OAIContainerRequest::fromJsonObject(QJsonObject json) { + + m_vehicle_id_isValid = ::OpenAPI::fromJsonValue(vehicle_id, json[QString("vehicle_id")]); + m_vehicle_id_isSet = !json[QString("vehicle_id")].isNull() && m_vehicle_id_isValid; + + m_container_id_isValid = ::OpenAPI::fromJsonValue(container_id, json[QString("container_id")]); + m_container_id_isSet = !json[QString("container_id")].isNull() && m_container_id_isValid; + + m_action_id_isValid = ::OpenAPI::fromJsonValue(action_id, json[QString("action_id")]); + m_action_id_isSet = !json[QString("action_id")].isNull() && m_action_id_isValid; +} + +QString OAIContainerRequest::asJson() const { + QJsonObject obj = this->asJsonObject(); + QJsonDocument doc(obj); + QByteArray bytes = doc.toJson(); + return QString(bytes); +} + +QJsonObject OAIContainerRequest::asJsonObject() const { + QJsonObject obj; + if (m_vehicle_id_isSet) { + obj.insert(QString("vehicle_id"), ::OpenAPI::toJsonValue(vehicle_id)); + } + if (m_container_id_isSet) { + obj.insert(QString("container_id"), ::OpenAPI::toJsonValue(container_id)); + } + if (m_action_id_isSet) { + obj.insert(QString("action_id"), ::OpenAPI::toJsonValue(action_id)); + } + return obj; +} + +QString OAIContainerRequest::getVehicleId() const { + return vehicle_id; +} +void OAIContainerRequest::setVehicleId(const QString &vehicle_id) { + this->vehicle_id = vehicle_id; + this->m_vehicle_id_isSet = true; +} + +bool OAIContainerRequest::is_vehicle_id_Set() const{ + return m_vehicle_id_isSet; +} + +bool OAIContainerRequest::is_vehicle_id_Valid() const{ + return m_vehicle_id_isValid; +} + +QString OAIContainerRequest::getContainerId() const { + return container_id; +} +void OAIContainerRequest::setContainerId(const QString &container_id) { + this->container_id = container_id; + this->m_container_id_isSet = true; +} + +bool OAIContainerRequest::is_container_id_Set() const{ + return m_container_id_isSet; +} + +bool OAIContainerRequest::is_container_id_Valid() const{ + return m_container_id_isValid; +} + +QString OAIContainerRequest::getActionId() const { + return action_id; +} +void OAIContainerRequest::setActionId(const QString &action_id) { + this->action_id = action_id; + this->m_action_id_isSet = true; +} + +bool OAIContainerRequest::is_action_id_Set() const{ + return m_action_id_isSet; +} + +bool OAIContainerRequest::is_action_id_Valid() const{ + return m_action_id_isValid; +} + +bool OAIContainerRequest::isSet() const { + bool isObjectUpdated = false; + do { + if (m_vehicle_id_isSet) { + isObjectUpdated = true; + break; + } + + if (m_container_id_isSet) { + isObjectUpdated = true; + break; + } + + if (m_action_id_isSet) { + isObjectUpdated = true; + break; + } + } while (false); + return isObjectUpdated; +} + +bool OAIContainerRequest::isValid() const { + // only required properties are required for the object to be considered valid + return m_vehicle_id_isValid && m_container_id_isValid && m_action_id_isValid && true; +} + +} // namespace OpenAPI diff --git a/ext/pdclient/OAIContainerRequest.h b/ext/pdclient/OAIContainerRequest.h new file mode 100644 index 000000000..712b00534 --- /dev/null +++ b/ext/pdclient/OAIContainerRequest.h @@ -0,0 +1,79 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * OAIContainerRequest.h + * + * + */ + +#ifndef OAIContainerRequest_H +#define OAIContainerRequest_H + +#include + +#include + +#include "OAIEnum.h" +#include "OAIObject.h" + +namespace OpenAPI { + +class OAIContainerRequest : public OAIObject { +public: + OAIContainerRequest(); + OAIContainerRequest(QString json); + ~OAIContainerRequest() override; + + QString asJson() const override; + QJsonObject asJsonObject() const override; + void fromJsonObject(QJsonObject json) override; + void fromJson(QString jsonString) override; + + QString getVehicleId() const; + void setVehicleId(const QString &vehicle_id); + bool is_vehicle_id_Set() const; + bool is_vehicle_id_Valid() const; + + QString getContainerId() const; + void setContainerId(const QString &container_id); + bool is_container_id_Set() const; + bool is_container_id_Valid() const; + + QString getActionId() const; + void setActionId(const QString &action_id); + bool is_action_id_Set() const; + bool is_action_id_Valid() const; + + virtual bool isSet() const override; + virtual bool isValid() const override; + +private: + void initializeModel(); + + QString vehicle_id; + bool m_vehicle_id_isSet; + bool m_vehicle_id_isValid; + + QString container_id; + bool m_container_id_isSet; + bool m_container_id_isValid; + + QString action_id; + bool m_action_id_isSet; + bool m_action_id_isValid; +}; + +} // namespace OpenAPI + +Q_DECLARE_METATYPE(OpenAPI::OAIContainerRequest) + +#endif // OAIContainerRequest_H diff --git a/ext/pdclient/OAIDefaultApi.cpp b/ext/pdclient/OAIDefaultApi.cpp new file mode 100644 index 000000000..3b257c2b4 --- /dev/null +++ b/ext/pdclient/OAIDefaultApi.cpp @@ -0,0 +1,1175 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#include "OAIDefaultApi.h" +#include "OAIServerConfiguration.h" +#include +#include + +namespace OpenAPI { + +OAIDefaultApi::OAIDefaultApi(const int timeOut) + : _timeOut(timeOut), + _manager(nullptr), + _isResponseCompressionEnabled(false), + _isRequestCompressionEnabled(false) { + initializeServerConfigs(); +} + +OAIDefaultApi::~OAIDefaultApi() { +} + +void OAIDefaultApi::initializeServerConfigs() { + //Default server + QList defaultConf = QList(); + //varying endpoint server + defaultConf.append(OAIServerConfiguration( + QUrl("http://127.0.0.1:8080"), + "Unsecured hosting for development", + QMap())); + defaultConf.append(OAIServerConfiguration( + QUrl("https://127.0.0.1:8443"), + "Secured hosting for deployment", + QMap())); + _serverConfigs.insert("inspectionActionIdGet", defaultConf); + _serverIndices.insert("inspectionActionIdGet", 0); + _serverConfigs.insert("inspectionCompleteActionIdPost", defaultConf); + _serverIndices.insert("inspectionCompleteActionIdPost", 0); + _serverConfigs.insert("inspectionHoldActionIdPost", defaultConf); + _serverIndices.insert("inspectionHoldActionIdPost", 0); + _serverConfigs.insert("inspectionHoldingActionIdPost", defaultConf); + _serverIndices.insert("inspectionHoldingActionIdPost", 0); + _serverConfigs.insert("inspectionPendingGet", defaultConf); + _serverIndices.insert("inspectionPendingGet", 0); + _serverConfigs.insert("inspectionPost", defaultConf); + _serverIndices.insert("inspectionPost", 0); + _serverConfigs.insert("loadingActionIdGet", defaultConf); + _serverIndices.insert("loadingActionIdGet", 0); + _serverConfigs.insert("loadingCompleteActionIdPost", defaultConf); + _serverIndices.insert("loadingCompleteActionIdPost", 0); + _serverConfigs.insert("loadingPendingGet", defaultConf); + _serverIndices.insert("loadingPendingGet", 0); + _serverConfigs.insert("loadingPost", defaultConf); + _serverIndices.insert("loadingPost", 0); + _serverConfigs.insert("loadingStartActionIdPost", defaultConf); + _serverIndices.insert("loadingStartActionIdPost", 0); + _serverConfigs.insert("unloadingActionIdGet", defaultConf); + _serverIndices.insert("unloadingActionIdGet", 0); + _serverConfigs.insert("unloadingCompleteActionIdPost", defaultConf); + _serverIndices.insert("unloadingCompleteActionIdPost", 0); + _serverConfigs.insert("unloadingPendingGet", defaultConf); + _serverIndices.insert("unloadingPendingGet", 0); + _serverConfigs.insert("unloadingPost", defaultConf); + _serverIndices.insert("unloadingPost", 0); + _serverConfigs.insert("unloadingStartActionIdPost", defaultConf); + _serverIndices.insert("unloadingStartActionIdPost", 0); +} + +/** +* returns 0 on success and -1, -2 or -3 on failure. +* -1 when the variable does not exist and -2 if the value is not defined in the enum and -3 if the operation or server index is not found +*/ +int OAIDefaultApi::setDefaultServerValue(int serverIndex, const QString &operation, const QString &variable, const QString &value) { + auto it = _serverConfigs.find(operation); + if (it != _serverConfigs.end() && serverIndex < it.value().size()) { + return _serverConfigs[operation][serverIndex].setDefaultValue(variable,value); + } + return -3; +} +void OAIDefaultApi::setServerIndex(const QString &operation, int serverIndex) { + if (_serverIndices.contains(operation) && serverIndex < _serverConfigs.find(operation).value().size()) { + _serverIndices[operation] = serverIndex; + } +} + +void OAIDefaultApi::setApiKey(const QString &apiKeyName, const QString &apiKey) { + _apiKeys.insert(apiKeyName,apiKey); +} + +void OAIDefaultApi::setBearerToken(const QString &token) { + _bearerToken = token; +} + +void OAIDefaultApi::setUsername(const QString &username) { + _username = username; +} + +void OAIDefaultApi::setPassword(const QString &password) { + _password = password; +} + + +void OAIDefaultApi::setTimeOut(const int timeOut) { + _timeOut = timeOut; +} + +void OAIDefaultApi::setWorkingDirectory(const QString &path) { + _workingDirectory = path; +} + +void OAIDefaultApi::setNetworkAccessManager(QNetworkAccessManager* manager) { + _manager = manager; +} + +/** + * Appends a new ServerConfiguration to the config map for a specific operation. + * @param operation The id to the target operation. + * @param url A string that contains the URL of the server + * @param description A String that describes the server + * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. + * returns the index of the new server config on success and -1 if the operation is not found + */ +int OAIDefaultApi::addServerConfiguration(const QString &operation, const QUrl &url, const QString &description, const QMap &variables) { + if (_serverConfigs.contains(operation)) { + _serverConfigs[operation].append(OAIServerConfiguration( + url, + description, + variables)); + return _serverConfigs[operation].size()-1; + } else { + return -1; + } +} + +/** + * Appends a new ServerConfiguration to the config map for a all operations and sets the index to that server. + * @param url A string that contains the URL of the server + * @param description A String that describes the server + * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. + */ +void OAIDefaultApi::setNewServerForAllOperations(const QUrl &url, const QString &description, const QMap &variables) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + for (auto keyIt = _serverIndices.keyBegin(); keyIt != _serverIndices.keyEnd(); keyIt++) { + setServerIndex(*keyIt, addServerConfiguration(*keyIt, url, description, variables)); + } +#else + for (auto &e : _serverIndices.keys()) { + setServerIndex(e, addServerConfiguration(e, url, description, variables)); + } +#endif +} + +/** + * Appends a new ServerConfiguration to the config map for an operations and sets the index to that server. + * @param URL A string that contains the URL of the server + * @param description A String that describes the server + * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. + */ +void OAIDefaultApi::setNewServer(const QString &operation, const QUrl &url, const QString &description, const QMap &variables) { + setServerIndex(operation, addServerConfiguration(operation, url, description, variables)); +} + +void OAIDefaultApi::addHeaders(const QString &key, const QString &value) { + _defaultHeaders.insert(key, value); +} + +void OAIDefaultApi::enableRequestCompression() { + _isRequestCompressionEnabled = true; +} + +void OAIDefaultApi::enableResponseCompression() { + _isResponseCompressionEnabled = true; +} + +void OAIDefaultApi::abortRequests() { + emit abortRequestsSignal(); +} + +QString OAIDefaultApi::getParamStylePrefix(const QString &style) { + if (style == "matrix") { + return ";"; + } else if (style == "label") { + return "."; + } else if (style == "form") { + return "&"; + } else if (style == "simple") { + return ""; + } else if (style == "spaceDelimited") { + return "&"; + } else if (style == "pipeDelimited") { + return "&"; + } else { + return "none"; + } +} + +QString OAIDefaultApi::getParamStyleSuffix(const QString &style) { + if (style == "matrix") { + return "="; + } else if (style == "label") { + return ""; + } else if (style == "form") { + return "="; + } else if (style == "simple") { + return ""; + } else if (style == "spaceDelimited") { + return "="; + } else if (style == "pipeDelimited") { + return "="; + } else { + return "none"; + } +} + +QString OAIDefaultApi::getParamStyleDelimiter(const QString &style, const QString &name, bool isExplode) { + + if (style == "matrix") { + return (isExplode) ? ";" + name + "=" : ","; + + } else if (style == "label") { + return (isExplode) ? "." : ","; + + } else if (style == "form") { + return (isExplode) ? "&" + name + "=" : ","; + + } else if (style == "simple") { + return ","; + } else if (style == "spaceDelimited") { + return (isExplode) ? "&" + name + "=" : " "; + + } else if (style == "pipeDelimited") { + return (isExplode) ? "&" + name + "=" : "|"; + + } else if (style == "deepObject") { + return (isExplode) ? "&" : "none"; + + } else { + return "none"; + } +} + +void OAIDefaultApi::inspectionActionIdGet(const QString &action_id) { + QString fullPath = QString(_serverConfigs["inspectionActionIdGet"][_serverIndices.value("inspectionActionIdGet")].URL()+"/inspection/{action_id}"); + + + { + QString action_idPathParam("{"); + action_idPathParam.append("action_id").append("}"); + QString pathPrefix, pathSuffix, pathDelimiter; + QString pathStyle = "simple"; + if (pathStyle == "") + pathStyle = "simple"; + pathPrefix = getParamStylePrefix(pathStyle); + pathSuffix = getParamStyleSuffix(pathStyle); + pathDelimiter = getParamStyleDelimiter(pathStyle, "action_id", false); + QString paramString = (pathStyle == "matrix") ? pathPrefix+"action_id"+pathSuffix : pathPrefix; + fullPath.replace(action_idPathParam, paramString+QUrl::toPercentEncoding(::OpenAPI::toStringValue(action_id))); + } + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "GET"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::inspectionActionIdGetCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::inspectionActionIdGetCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + OAIInspectionStatus output(QString(worker->response)); + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit inspectionActionIdGetSignal(output); + emit inspectionActionIdGetSignalFull(worker, output); + } else { + emit inspectionActionIdGetSignalE(output, error_type, error_str); + emit inspectionActionIdGetSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::inspectionCompleteActionIdPost(const QString &action_id) { + QString fullPath = QString(_serverConfigs["inspectionCompleteActionIdPost"][_serverIndices.value("inspectionCompleteActionIdPost")].URL()+"/inspection/complete/{action_id}"); + + + { + QString action_idPathParam("{"); + action_idPathParam.append("action_id").append("}"); + QString pathPrefix, pathSuffix, pathDelimiter; + QString pathStyle = "simple"; + if (pathStyle == "") + pathStyle = "simple"; + pathPrefix = getParamStylePrefix(pathStyle); + pathSuffix = getParamStyleSuffix(pathStyle); + pathDelimiter = getParamStyleDelimiter(pathStyle, "action_id", false); + QString paramString = (pathStyle == "matrix") ? pathPrefix+"action_id"+pathSuffix : pathPrefix; + fullPath.replace(action_idPathParam, paramString+QUrl::toPercentEncoding(::OpenAPI::toStringValue(action_id))); + } + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "POST"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::inspectionCompleteActionIdPostCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::inspectionCompleteActionIdPostCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit inspectionCompleteActionIdPostSignal(); + emit inspectionCompleteActionIdPostSignalFull(worker); + } else { + emit inspectionCompleteActionIdPostSignalE(error_type, error_str); + emit inspectionCompleteActionIdPostSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::inspectionHoldActionIdPost(const QString &action_id) { + QString fullPath = QString(_serverConfigs["inspectionHoldActionIdPost"][_serverIndices.value("inspectionHoldActionIdPost")].URL()+"/inspection/hold/{action_id}"); + + + { + QString action_idPathParam("{"); + action_idPathParam.append("action_id").append("}"); + QString pathPrefix, pathSuffix, pathDelimiter; + QString pathStyle = "simple"; + if (pathStyle == "") + pathStyle = "simple"; + pathPrefix = getParamStylePrefix(pathStyle); + pathSuffix = getParamStyleSuffix(pathStyle); + pathDelimiter = getParamStyleDelimiter(pathStyle, "action_id", false); + QString paramString = (pathStyle == "matrix") ? pathPrefix+"action_id"+pathSuffix : pathPrefix; + fullPath.replace(action_idPathParam, paramString+QUrl::toPercentEncoding(::OpenAPI::toStringValue(action_id))); + } + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "POST"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::inspectionHoldActionIdPostCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::inspectionHoldActionIdPostCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit inspectionHoldActionIdPostSignal(); + emit inspectionHoldActionIdPostSignalFull(worker); + } else { + emit inspectionHoldActionIdPostSignalE(error_type, error_str); + emit inspectionHoldActionIdPostSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::inspectionHoldingActionIdPost(const QString &action_id) { + QString fullPath = QString(_serverConfigs["inspectionHoldingActionIdPost"][_serverIndices.value("inspectionHoldingActionIdPost")].URL()+"/inspection/holding/{action_id}"); + + + { + QString action_idPathParam("{"); + action_idPathParam.append("action_id").append("}"); + QString pathPrefix, pathSuffix, pathDelimiter; + QString pathStyle = "simple"; + if (pathStyle == "") + pathStyle = "simple"; + pathPrefix = getParamStylePrefix(pathStyle); + pathSuffix = getParamStyleSuffix(pathStyle); + pathDelimiter = getParamStyleDelimiter(pathStyle, "action_id", false); + QString paramString = (pathStyle == "matrix") ? pathPrefix+"action_id"+pathSuffix : pathPrefix; + fullPath.replace(action_idPathParam, paramString+QUrl::toPercentEncoding(::OpenAPI::toStringValue(action_id))); + } + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "POST"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::inspectionHoldingActionIdPostCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::inspectionHoldingActionIdPostCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit inspectionHoldingActionIdPostSignal(); + emit inspectionHoldingActionIdPostSignalFull(worker); + } else { + emit inspectionHoldingActionIdPostSignalE(error_type, error_str); + emit inspectionHoldingActionIdPostSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::inspectionPendingGet() { + QString fullPath = QString(_serverConfigs["inspectionPendingGet"][_serverIndices.value("inspectionPendingGet")].URL()+"/inspection/pending"); + + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "GET"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::inspectionPendingGetCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::inspectionPendingGetCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + OAIInspectionStatusList output(QString(worker->response)); + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit inspectionPendingGetSignal(output); + emit inspectionPendingGetSignalFull(worker, output); + } else { + emit inspectionPendingGetSignalE(output, error_type, error_str); + emit inspectionPendingGetSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::inspectionPost(const OAIInspectionRequest &oai_inspection_request) { + QString fullPath = QString(_serverConfigs["inspectionPost"][_serverIndices.value("inspectionPost")].URL()+"/inspection"); + + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "POST"); + + { + + QByteArray output = oai_inspection_request.asJson().toUtf8(); + input.request_body.append(output); + } +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::inspectionPostCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::inspectionPostCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit inspectionPostSignal(); + emit inspectionPostSignalFull(worker); + } else { + emit inspectionPostSignalE(error_type, error_str); + emit inspectionPostSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::loadingActionIdGet(const QString &action_id) { + QString fullPath = QString(_serverConfigs["loadingActionIdGet"][_serverIndices.value("loadingActionIdGet")].URL()+"/loading/{action_id}"); + + + { + QString action_idPathParam("{"); + action_idPathParam.append("action_id").append("}"); + QString pathPrefix, pathSuffix, pathDelimiter; + QString pathStyle = "simple"; + if (pathStyle == "") + pathStyle = "simple"; + pathPrefix = getParamStylePrefix(pathStyle); + pathSuffix = getParamStyleSuffix(pathStyle); + pathDelimiter = getParamStyleDelimiter(pathStyle, "action_id", false); + QString paramString = (pathStyle == "matrix") ? pathPrefix+"action_id"+pathSuffix : pathPrefix; + fullPath.replace(action_idPathParam, paramString+QUrl::toPercentEncoding(::OpenAPI::toStringValue(action_id))); + } + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "GET"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::loadingActionIdGetCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::loadingActionIdGetCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + OAIContainerActionStatus output(QString(worker->response)); + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit loadingActionIdGetSignal(output); + emit loadingActionIdGetSignalFull(worker, output); + } else { + emit loadingActionIdGetSignalE(output, error_type, error_str); + emit loadingActionIdGetSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::loadingCompleteActionIdPost(const QString &action_id) { + QString fullPath = QString(_serverConfigs["loadingCompleteActionIdPost"][_serverIndices.value("loadingCompleteActionIdPost")].URL()+"/loading/complete/{action_id}"); + + + { + QString action_idPathParam("{"); + action_idPathParam.append("action_id").append("}"); + QString pathPrefix, pathSuffix, pathDelimiter; + QString pathStyle = "simple"; + if (pathStyle == "") + pathStyle = "simple"; + pathPrefix = getParamStylePrefix(pathStyle); + pathSuffix = getParamStyleSuffix(pathStyle); + pathDelimiter = getParamStyleDelimiter(pathStyle, "action_id", false); + QString paramString = (pathStyle == "matrix") ? pathPrefix+"action_id"+pathSuffix : pathPrefix; + fullPath.replace(action_idPathParam, paramString+QUrl::toPercentEncoding(::OpenAPI::toStringValue(action_id))); + } + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "POST"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::loadingCompleteActionIdPostCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::loadingCompleteActionIdPostCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit loadingCompleteActionIdPostSignal(); + emit loadingCompleteActionIdPostSignalFull(worker); + } else { + emit loadingCompleteActionIdPostSignalE(error_type, error_str); + emit loadingCompleteActionIdPostSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::loadingPendingGet() { + QString fullPath = QString(_serverConfigs["loadingPendingGet"][_serverIndices.value("loadingPendingGet")].URL()+"/loading/pending"); + + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "GET"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::loadingPendingGetCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::loadingPendingGetCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + OAIActionStatusList output(QString(worker->response)); + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit loadingPendingGetSignal(output); + emit loadingPendingGetSignalFull(worker, output); + } else { + emit loadingPendingGetSignalE(output, error_type, error_str); + emit loadingPendingGetSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::loadingPost(const OAIContainerRequest &oai_container_request) { + QString fullPath = QString(_serverConfigs["loadingPost"][_serverIndices.value("loadingPost")].URL()+"/loading"); + + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "POST"); + + { + + QByteArray output = oai_container_request.asJson().toUtf8(); + input.request_body.append(output); + } +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::loadingPostCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::loadingPostCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit loadingPostSignal(); + emit loadingPostSignalFull(worker); + } else { + emit loadingPostSignalE(error_type, error_str); + emit loadingPostSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::loadingStartActionIdPost(const QString &action_id) { + QString fullPath = QString(_serverConfigs["loadingStartActionIdPost"][_serverIndices.value("loadingStartActionIdPost")].URL()+"/loading/start/{action_id}"); + + + { + QString action_idPathParam("{"); + action_idPathParam.append("action_id").append("}"); + QString pathPrefix, pathSuffix, pathDelimiter; + QString pathStyle = "simple"; + if (pathStyle == "") + pathStyle = "simple"; + pathPrefix = getParamStylePrefix(pathStyle); + pathSuffix = getParamStyleSuffix(pathStyle); + pathDelimiter = getParamStyleDelimiter(pathStyle, "action_id", false); + QString paramString = (pathStyle == "matrix") ? pathPrefix+"action_id"+pathSuffix : pathPrefix; + fullPath.replace(action_idPathParam, paramString+QUrl::toPercentEncoding(::OpenAPI::toStringValue(action_id))); + } + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "POST"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::loadingStartActionIdPostCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::loadingStartActionIdPostCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit loadingStartActionIdPostSignal(); + emit loadingStartActionIdPostSignalFull(worker); + } else { + emit loadingStartActionIdPostSignalE(error_type, error_str); + emit loadingStartActionIdPostSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::unloadingActionIdGet(const QString &action_id) { + QString fullPath = QString(_serverConfigs["unloadingActionIdGet"][_serverIndices.value("unloadingActionIdGet")].URL()+"/unloading/{action_id}"); + + + { + QString action_idPathParam("{"); + action_idPathParam.append("action_id").append("}"); + QString pathPrefix, pathSuffix, pathDelimiter; + QString pathStyle = "simple"; + if (pathStyle == "") + pathStyle = "simple"; + pathPrefix = getParamStylePrefix(pathStyle); + pathSuffix = getParamStyleSuffix(pathStyle); + pathDelimiter = getParamStyleDelimiter(pathStyle, "action_id", false); + QString paramString = (pathStyle == "matrix") ? pathPrefix+"action_id"+pathSuffix : pathPrefix; + fullPath.replace(action_idPathParam, paramString+QUrl::toPercentEncoding(::OpenAPI::toStringValue(action_id))); + } + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "GET"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::unloadingActionIdGetCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::unloadingActionIdGetCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + OAIContainerActionStatus output(QString(worker->response)); + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit unloadingActionIdGetSignal(output); + emit unloadingActionIdGetSignalFull(worker, output); + } else { + emit unloadingActionIdGetSignalE(output, error_type, error_str); + emit unloadingActionIdGetSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::unloadingCompleteActionIdPost(const QString &action_id) { + QString fullPath = QString(_serverConfigs["unloadingCompleteActionIdPost"][_serverIndices.value("unloadingCompleteActionIdPost")].URL()+"/unloading/complete/{action_id}"); + + + { + QString action_idPathParam("{"); + action_idPathParam.append("action_id").append("}"); + QString pathPrefix, pathSuffix, pathDelimiter; + QString pathStyle = "simple"; + if (pathStyle == "") + pathStyle = "simple"; + pathPrefix = getParamStylePrefix(pathStyle); + pathSuffix = getParamStyleSuffix(pathStyle); + pathDelimiter = getParamStyleDelimiter(pathStyle, "action_id", false); + QString paramString = (pathStyle == "matrix") ? pathPrefix+"action_id"+pathSuffix : pathPrefix; + fullPath.replace(action_idPathParam, paramString+QUrl::toPercentEncoding(::OpenAPI::toStringValue(action_id))); + } + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "POST"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::unloadingCompleteActionIdPostCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::unloadingCompleteActionIdPostCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit unloadingCompleteActionIdPostSignal(); + emit unloadingCompleteActionIdPostSignalFull(worker); + } else { + emit unloadingCompleteActionIdPostSignalE(error_type, error_str); + emit unloadingCompleteActionIdPostSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::unloadingPendingGet() { + QString fullPath = QString(_serverConfigs["unloadingPendingGet"][_serverIndices.value("unloadingPendingGet")].URL()+"/unloading/pending"); + + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "GET"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::unloadingPendingGetCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::unloadingPendingGetCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + OAIActionStatusList output(QString(worker->response)); + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit unloadingPendingGetSignal(output); + emit unloadingPendingGetSignalFull(worker, output); + } else { + emit unloadingPendingGetSignalE(output, error_type, error_str); + emit unloadingPendingGetSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::unloadingPost(const OAIContainerRequest &oai_container_request) { + QString fullPath = QString(_serverConfigs["unloadingPost"][_serverIndices.value("unloadingPost")].URL()+"/unloading"); + + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "POST"); + + { + + QByteArray output = oai_container_request.asJson().toUtf8(); + input.request_body.append(output); + } +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::unloadingPostCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::unloadingPostCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit unloadingPostSignal(); + emit unloadingPostSignalFull(worker); + } else { + emit unloadingPostSignalE(error_type, error_str); + emit unloadingPostSignalEFull(worker, error_type, error_str); + } +} + +void OAIDefaultApi::unloadingStartActionIdPost(const QString &action_id) { + QString fullPath = QString(_serverConfigs["unloadingStartActionIdPost"][_serverIndices.value("unloadingStartActionIdPost")].URL()+"/unloading/start/{action_id}"); + + + { + QString action_idPathParam("{"); + action_idPathParam.append("action_id").append("}"); + QString pathPrefix, pathSuffix, pathDelimiter; + QString pathStyle = "simple"; + if (pathStyle == "") + pathStyle = "simple"; + pathPrefix = getParamStylePrefix(pathStyle); + pathSuffix = getParamStyleSuffix(pathStyle); + pathDelimiter = getParamStyleDelimiter(pathStyle, "action_id", false); + QString paramString = (pathStyle == "matrix") ? pathPrefix+"action_id"+pathSuffix : pathPrefix; + fullPath.replace(action_idPathParam, paramString+QUrl::toPercentEncoding(::OpenAPI::toStringValue(action_id))); + } + OAIHttpRequestWorker *worker = new OAIHttpRequestWorker(this, _manager); + worker->setTimeOut(_timeOut); + worker->setWorkingDirectory(_workingDirectory); + OAIHttpRequestInput input(fullPath, "POST"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + for (auto keyValueIt = _defaultHeaders.keyValueBegin(); keyValueIt != _defaultHeaders.keyValueEnd(); keyValueIt++) { + input.headers.insert(keyValueIt->first, keyValueIt->second); + } +#else + for (auto key : _defaultHeaders.keys()) { + input.headers.insert(key, _defaultHeaders[key]); + } +#endif + + connect(worker, &OAIHttpRequestWorker::on_execution_finished, this, &OAIDefaultApi::unloadingStartActionIdPostCallback); + connect(this, &OAIDefaultApi::abortRequestsSignal, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, this, [this]() { + if (findChildren().count() == 0) { + emit allPendingRequestsCompleted(); + } + }); + + worker->execute(&input); +} + +void OAIDefaultApi::unloadingStartActionIdPostCallback(OAIHttpRequestWorker *worker) { + QString error_str = worker->error_str; + QNetworkReply::NetworkError error_type = worker->error_type; + + if (worker->error_type != QNetworkReply::NoError) { + error_str = QString("%1, %2").arg(worker->error_str, QString(worker->response)); + } + worker->deleteLater(); + + if (worker->error_type == QNetworkReply::NoError) { + emit unloadingStartActionIdPostSignal(); + emit unloadingStartActionIdPostSignalFull(worker); + } else { + emit unloadingStartActionIdPostSignalE(error_type, error_str); + emit unloadingStartActionIdPostSignalEFull(worker, error_type, error_str); + } +} + +} // namespace OpenAPI diff --git a/ext/pdclient/OAIDefaultApi.h b/ext/pdclient/OAIDefaultApi.h new file mode 100644 index 000000000..35f77a407 --- /dev/null +++ b/ext/pdclient/OAIDefaultApi.h @@ -0,0 +1,244 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#ifndef OAI_OAIDefaultApi_H +#define OAI_OAIDefaultApi_H + +#include "OAIHelpers.h" +#include "OAIHttpRequest.h" +#include "OAIServerConfiguration.h" + +#include "OAIActionStatusList.h" +#include "OAIContainerActionStatus.h" +#include "OAIContainerRequest.h" +#include "OAIInspectionRequest.h" +#include "OAIInspectionStatus.h" +#include "OAIInspectionStatusList.h" +#include + +#include +#include +#include +#include +#include + +namespace OpenAPI { + +class OAIDefaultApi : public QObject { + Q_OBJECT + +public: + OAIDefaultApi(const int timeOut = 0); + ~OAIDefaultApi(); + + void initializeServerConfigs(); + int setDefaultServerValue(int serverIndex,const QString &operation, const QString &variable,const QString &val); + void setServerIndex(const QString &operation, int serverIndex); + void setApiKey(const QString &apiKeyName, const QString &apiKey); + void setBearerToken(const QString &token); + void setUsername(const QString &username); + void setPassword(const QString &password); + void setTimeOut(const int timeOut); + void setWorkingDirectory(const QString &path); + void setNetworkAccessManager(QNetworkAccessManager* manager); + int addServerConfiguration(const QString &operation, const QUrl &url, const QString &description = "", const QMap &variables = QMap()); + void setNewServerForAllOperations(const QUrl &url, const QString &description = "", const QMap &variables = QMap()); + void setNewServer(const QString &operation, const QUrl &url, const QString &description = "", const QMap &variables = QMap()); + void addHeaders(const QString &key, const QString &value); + void enableRequestCompression(); + void enableResponseCompression(); + void abortRequests(); + QString getParamStylePrefix(const QString &style); + QString getParamStyleSuffix(const QString &style); + QString getParamStyleDelimiter(const QString &style, const QString &name, bool isExplode); + + /** + * @param[in] action_id QString [required] + */ + void inspectionActionIdGet(const QString &action_id); + + /** + * @param[in] action_id QString [required] + */ + void inspectionCompleteActionIdPost(const QString &action_id); + + /** + * @param[in] action_id QString [required] + */ + void inspectionHoldActionIdPost(const QString &action_id); + + /** + * @param[in] action_id QString [required] + */ + void inspectionHoldingActionIdPost(const QString &action_id); + + + void inspectionPendingGet(); + + /** + * @param[in] oai_inspection_request OAIInspectionRequest [required] + */ + void inspectionPost(const OAIInspectionRequest &oai_inspection_request); + + /** + * @param[in] action_id QString [required] + */ + void loadingActionIdGet(const QString &action_id); + + /** + * @param[in] action_id QString [required] + */ + void loadingCompleteActionIdPost(const QString &action_id); + + + void loadingPendingGet(); + + /** + * @param[in] oai_container_request OAIContainerRequest [required] + */ + void loadingPost(const OAIContainerRequest &oai_container_request); + + /** + * @param[in] action_id QString [required] + */ + void loadingStartActionIdPost(const QString &action_id); + + /** + * @param[in] action_id QString [required] + */ + void unloadingActionIdGet(const QString &action_id); + + /** + * @param[in] action_id QString [required] + */ + void unloadingCompleteActionIdPost(const QString &action_id); + + + void unloadingPendingGet(); + + /** + * @param[in] oai_container_request OAIContainerRequest [required] + */ + void unloadingPost(const OAIContainerRequest &oai_container_request); + + /** + * @param[in] action_id QString [required] + */ + void unloadingStartActionIdPost(const QString &action_id); + + +private: + QMap _serverIndices; + QMap> _serverConfigs; + QMap _apiKeys; + QString _bearerToken; + QString _username; + QString _password; + int _timeOut; + QString _workingDirectory; + QNetworkAccessManager* _manager; + QMap _defaultHeaders; + bool _isResponseCompressionEnabled; + bool _isRequestCompressionEnabled; + + void inspectionActionIdGetCallback(OAIHttpRequestWorker *worker); + void inspectionCompleteActionIdPostCallback(OAIHttpRequestWorker *worker); + void inspectionHoldActionIdPostCallback(OAIHttpRequestWorker *worker); + void inspectionHoldingActionIdPostCallback(OAIHttpRequestWorker *worker); + void inspectionPendingGetCallback(OAIHttpRequestWorker *worker); + void inspectionPostCallback(OAIHttpRequestWorker *worker); + void loadingActionIdGetCallback(OAIHttpRequestWorker *worker); + void loadingCompleteActionIdPostCallback(OAIHttpRequestWorker *worker); + void loadingPendingGetCallback(OAIHttpRequestWorker *worker); + void loadingPostCallback(OAIHttpRequestWorker *worker); + void loadingStartActionIdPostCallback(OAIHttpRequestWorker *worker); + void unloadingActionIdGetCallback(OAIHttpRequestWorker *worker); + void unloadingCompleteActionIdPostCallback(OAIHttpRequestWorker *worker); + void unloadingPendingGetCallback(OAIHttpRequestWorker *worker); + void unloadingPostCallback(OAIHttpRequestWorker *worker); + void unloadingStartActionIdPostCallback(OAIHttpRequestWorker *worker); + +signals: + + void inspectionActionIdGetSignal(OAIInspectionStatus summary); + void inspectionCompleteActionIdPostSignal(); + void inspectionHoldActionIdPostSignal(); + void inspectionHoldingActionIdPostSignal(); + void inspectionPendingGetSignal(OAIInspectionStatusList summary); + void inspectionPostSignal(); + void loadingActionIdGetSignal(OAIContainerActionStatus summary); + void loadingCompleteActionIdPostSignal(); + void loadingPendingGetSignal(OAIActionStatusList summary); + void loadingPostSignal(); + void loadingStartActionIdPostSignal(); + void unloadingActionIdGetSignal(OAIContainerActionStatus summary); + void unloadingCompleteActionIdPostSignal(); + void unloadingPendingGetSignal(OAIActionStatusList summary); + void unloadingPostSignal(); + void unloadingStartActionIdPostSignal(); + + void inspectionActionIdGetSignalFull(OAIHttpRequestWorker *worker, OAIInspectionStatus summary); + void inspectionCompleteActionIdPostSignalFull(OAIHttpRequestWorker *worker); + void inspectionHoldActionIdPostSignalFull(OAIHttpRequestWorker *worker); + void inspectionHoldingActionIdPostSignalFull(OAIHttpRequestWorker *worker); + void inspectionPendingGetSignalFull(OAIHttpRequestWorker *worker, OAIInspectionStatusList summary); + void inspectionPostSignalFull(OAIHttpRequestWorker *worker); + void loadingActionIdGetSignalFull(OAIHttpRequestWorker *worker, OAIContainerActionStatus summary); + void loadingCompleteActionIdPostSignalFull(OAIHttpRequestWorker *worker); + void loadingPendingGetSignalFull(OAIHttpRequestWorker *worker, OAIActionStatusList summary); + void loadingPostSignalFull(OAIHttpRequestWorker *worker); + void loadingStartActionIdPostSignalFull(OAIHttpRequestWorker *worker); + void unloadingActionIdGetSignalFull(OAIHttpRequestWorker *worker, OAIContainerActionStatus summary); + void unloadingCompleteActionIdPostSignalFull(OAIHttpRequestWorker *worker); + void unloadingPendingGetSignalFull(OAIHttpRequestWorker *worker, OAIActionStatusList summary); + void unloadingPostSignalFull(OAIHttpRequestWorker *worker); + void unloadingStartActionIdPostSignalFull(OAIHttpRequestWorker *worker); + + void inspectionActionIdGetSignalE(OAIInspectionStatus summary, QNetworkReply::NetworkError error_type, QString error_str); + void inspectionCompleteActionIdPostSignalE(QNetworkReply::NetworkError error_type, QString error_str); + void inspectionHoldActionIdPostSignalE(QNetworkReply::NetworkError error_type, QString error_str); + void inspectionHoldingActionIdPostSignalE(QNetworkReply::NetworkError error_type, QString error_str); + void inspectionPendingGetSignalE(OAIInspectionStatusList summary, QNetworkReply::NetworkError error_type, QString error_str); + void inspectionPostSignalE(QNetworkReply::NetworkError error_type, QString error_str); + void loadingActionIdGetSignalE(OAIContainerActionStatus summary, QNetworkReply::NetworkError error_type, QString error_str); + void loadingCompleteActionIdPostSignalE(QNetworkReply::NetworkError error_type, QString error_str); + void loadingPendingGetSignalE(OAIActionStatusList summary, QNetworkReply::NetworkError error_type, QString error_str); + void loadingPostSignalE(QNetworkReply::NetworkError error_type, QString error_str); + void loadingStartActionIdPostSignalE(QNetworkReply::NetworkError error_type, QString error_str); + void unloadingActionIdGetSignalE(OAIContainerActionStatus summary, QNetworkReply::NetworkError error_type, QString error_str); + void unloadingCompleteActionIdPostSignalE(QNetworkReply::NetworkError error_type, QString error_str); + void unloadingPendingGetSignalE(OAIActionStatusList summary, QNetworkReply::NetworkError error_type, QString error_str); + void unloadingPostSignalE(QNetworkReply::NetworkError error_type, QString error_str); + void unloadingStartActionIdPostSignalE(QNetworkReply::NetworkError error_type, QString error_str); + + void inspectionActionIdGetSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void inspectionCompleteActionIdPostSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void inspectionHoldActionIdPostSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void inspectionHoldingActionIdPostSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void inspectionPendingGetSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void inspectionPostSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void loadingActionIdGetSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void loadingCompleteActionIdPostSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void loadingPendingGetSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void loadingPostSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void loadingStartActionIdPostSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void unloadingActionIdGetSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void unloadingCompleteActionIdPostSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void unloadingPendingGetSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void unloadingPostSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + void unloadingStartActionIdPostSignalEFull(OAIHttpRequestWorker *worker, QNetworkReply::NetworkError error_type, QString error_str); + + void abortRequestsSignal(); + void allPendingRequestsCompleted(); +}; + +} // namespace OpenAPI +#endif diff --git a/ext/pdclient/OAIEnum.h b/ext/pdclient/OAIEnum.h new file mode 100644 index 000000000..9177a8d38 --- /dev/null +++ b/ext/pdclient/OAIEnum.h @@ -0,0 +1,63 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#ifndef OAI_ENUM_H +#define OAI_ENUM_H + +#include +#include +#include + +namespace OpenAPI { + +class OAIEnum { +public: + OAIEnum() {} + + OAIEnum(QString jsonString) { + fromJson(jsonString); + } + + virtual ~OAIEnum() {} + + virtual QJsonValue asJsonValue() const { + return QJsonValue(jstr); + } + + virtual QString asJson() const { + return jstr; + } + + virtual void fromJson(QString jsonString) { + jstr = jsonString; + } + + virtual void fromJsonValue(QJsonValue jval) { + jstr = jval.toString(); + } + + virtual bool isSet() const { + return false; + } + + virtual bool isValid() const { + return true; + } + +private: + QString jstr; +}; + +} // namespace OpenAPI + +Q_DECLARE_METATYPE(OpenAPI::OAIEnum) + +#endif // OAI_ENUM_H diff --git a/ext/pdclient/OAIHelpers.cpp b/ext/pdclient/OAIHelpers.cpp new file mode 100644 index 000000000..aced612b3 --- /dev/null +++ b/ext/pdclient/OAIHelpers.cpp @@ -0,0 +1,426 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#include +#include +#include "OAIHelpers.h" + +namespace OpenAPI { + +class OAISerializerSettings { +public: + struct CustomDateTimeFormat{ + bool isStringSet = false; + QString formatString; + bool isEnumSet = false; + Qt::DateFormat formatEnum; + }; + + static CustomDateTimeFormat getCustomDateTimeFormat() { + return getInstance()->customDateTimeFormat; + } + + static void setDateTimeFormatString(const QString &dtFormat){ + getInstance()->customDateTimeFormat.isStringSet = true; + getInstance()->customDateTimeFormat.isEnumSet = false; + getInstance()->customDateTimeFormat.formatString = dtFormat; + } + + static void setDateTimeFormatEnum(const Qt::DateFormat &dtFormat){ + getInstance()->customDateTimeFormat.isEnumSet = true; + getInstance()->customDateTimeFormat.isStringSet = false; + getInstance()->customDateTimeFormat.formatEnum = dtFormat; + } + + static OAISerializerSettings *getInstance(){ + if(instance == nullptr){ + instance = new OAISerializerSettings(); + } + return instance; + } + +private: + explicit OAISerializerSettings(){ + instance = this; + customDateTimeFormat.isStringSet = false; + customDateTimeFormat.isEnumSet = false; + } + static OAISerializerSettings *instance; + CustomDateTimeFormat customDateTimeFormat; +}; + +OAISerializerSettings * OAISerializerSettings::instance = nullptr; + +bool setDateTimeFormat(const QString &dateTimeFormat){ + bool success = false; + auto dt = QDateTime::fromString(QDateTime::currentDateTime().toString(dateTimeFormat), dateTimeFormat); + if (dt.isValid()) { + success = true; + OAISerializerSettings::setDateTimeFormatString(dateTimeFormat); + } + return success; +} + +bool setDateTimeFormat(const Qt::DateFormat &dateTimeFormat){ + bool success = false; + auto dt = QDateTime::fromString(QDateTime::currentDateTime().toString(dateTimeFormat), dateTimeFormat); + if (dt.isValid()) { + success = true; + OAISerializerSettings::setDateTimeFormatEnum(dateTimeFormat); + } + return success; +} + +QString toStringValue(const QString &value) { + return value; +} + +QString toStringValue(const QDateTime &value) { + if (OAISerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) { + return value.toString(OAISerializerSettings::getInstance()->getCustomDateTimeFormat().formatString); + } + + if (OAISerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) { + return value.toString(OAISerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum); + } + + // ISO 8601 + return value.toString(Qt::ISODate); +} + +QString toStringValue(const QByteArray &value) { + return QString(value); +} + +QString toStringValue(const QDate &value) { + // ISO 8601 + return value.toString(Qt::DateFormat::ISODate); +} + +QString toStringValue(const qint32 &value) { + return QString::number(value); +} + +QString toStringValue(const qint64 &value) { + return QString::number(value); +} + +QString toStringValue(const bool &value) { + return QString(value ? "true" : "false"); +} + +QString toStringValue(const float &value) { + return QString::number(static_cast(value)); +} + +QString toStringValue(const double &value) { + return QString::number(value); +} + +QString toStringValue(const OAIObject &value) { + return value.asJson(); +} + +QString toStringValue(const OAIEnum &value) { + return value.asJson(); +} + +QString toStringValue(const OAIHttpFileElement &value) { + return value.asJson(); +} + +QJsonValue toJsonValue(const QString &value) { + return QJsonValue(value); +} + +QJsonValue toJsonValue(const QDateTime &value) { + if (OAISerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) { + return QJsonValue(value.toString(OAISerializerSettings::getInstance()->getCustomDateTimeFormat().formatString)); + } + + if (OAISerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) { + return QJsonValue(value.toString(OAISerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum)); + } + + // ISO 8601 + return QJsonValue(value.toString(Qt::ISODate)); +} + +QJsonValue toJsonValue(const QByteArray &value) { + return QJsonValue(QString(value.toBase64())); +} + +QJsonValue toJsonValue(const QDate &value) { + return QJsonValue(value.toString(Qt::ISODate)); +} + +QJsonValue toJsonValue(const qint32 &value) { + return QJsonValue(value); +} + +QJsonValue toJsonValue(const qint64 &value) { + return QJsonValue(value); +} + +QJsonValue toJsonValue(const bool &value) { + return QJsonValue(value); +} + +QJsonValue toJsonValue(const float &value) { + return QJsonValue(static_cast(value)); +} + +QJsonValue toJsonValue(const double &value) { + return QJsonValue(value); +} + +QJsonValue toJsonValue(const OAIObject &value) { + return value.asJsonObject(); +} + +QJsonValue toJsonValue(const OAIEnum &value) { + return value.asJsonValue(); +} + +QJsonValue toJsonValue(const OAIHttpFileElement &value) { + return value.asJsonValue(); +} + +bool fromStringValue(const QString &inStr, QString &value) { + value.clear(); + value.append(inStr); + return !inStr.isEmpty(); +} + +bool fromStringValue(const QString &inStr, QDateTime &value) { + if (inStr.isEmpty()) { + return false; + } else { + QDateTime dateTime; + if (OAISerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) { + dateTime = QDateTime::fromString(inStr, OAISerializerSettings::getInstance()->getCustomDateTimeFormat().formatString); + } else if (OAISerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) { + dateTime = QDateTime::fromString(inStr, OAISerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum); + } else { + dateTime = QDateTime::fromString(inStr, Qt::ISODate); + } + + if (dateTime.isValid()) { + value.setDate(dateTime.date()); + value.setTime(dateTime.time()); + } else { + qDebug() << "DateTime is invalid"; + } + return dateTime.isValid(); + } +} + +bool fromStringValue(const QString &inStr, QByteArray &value) { + if (inStr.isEmpty()) { + return false; + } else { + value.clear(); + value.append(inStr.toUtf8()); + return value.count() > 0; + } +} + +bool fromStringValue(const QString &inStr, QDate &value) { + if (inStr.isEmpty()) { + return false; + } else { + auto date = QDate::fromString(inStr, Qt::DateFormat::ISODate); + if (date.isValid()) { + value.setDate(date.year(), date.month(), date.day()); + } else { + qDebug() << "Date is invalid"; + } + return date.isValid(); + } +} + +bool fromStringValue(const QString &inStr, qint32 &value) { + bool ok = false; + value = QVariant(inStr).toInt(&ok); + return ok; +} + +bool fromStringValue(const QString &inStr, qint64 &value) { + bool ok = false; + value = QVariant(inStr).toLongLong(&ok); + return ok; +} + +bool fromStringValue(const QString &inStr, bool &value) { + value = QVariant(inStr).toBool(); + return ((inStr == "true") || (inStr == "false")); +} + +bool fromStringValue(const QString &inStr, float &value) { + bool ok = false; + value = QVariant(inStr).toFloat(&ok); + return ok; +} + +bool fromStringValue(const QString &inStr, double &value) { + bool ok = false; + value = QVariant(inStr).toDouble(&ok); + return ok; +} + +bool fromStringValue(const QString &inStr, OAIObject &value) +{ + QJsonParseError err; + QJsonDocument::fromJson(inStr.toUtf8(),&err); + if ( err.error == QJsonParseError::NoError ){ + value.fromJson(inStr); + return true; + } + return false; +} + +bool fromStringValue(const QString &inStr, OAIEnum &value) { + value.fromJson(inStr); + return true; +} + +bool fromStringValue(const QString &inStr, OAIHttpFileElement &value) { + return value.fromStringValue(inStr); +} + +bool fromJsonValue(QString &value, const QJsonValue &jval) { + bool ok = true; + if (!jval.isUndefined() && !jval.isNull()) { + if (jval.isString()) { + value = jval.toString(); + } else if (jval.isBool()) { + value = jval.toBool() ? "true" : "false"; + } else if (jval.isDouble()) { + value = QString::number(jval.toDouble()); + } else { + ok = false; + } + } else { + ok = false; + } + return ok; +} + +bool fromJsonValue(QDateTime &value, const QJsonValue &jval) { + bool ok = true; + if (!jval.isUndefined() && !jval.isNull() && jval.isString()) { + if (OAISerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) { + value = QDateTime::fromString(jval.toString(), OAISerializerSettings::getInstance()->getCustomDateTimeFormat().formatString); + } else if (OAISerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) { + value = QDateTime::fromString(jval.toString(), OAISerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum); + } else { + value = QDateTime::fromString(jval.toString(), Qt::ISODate); + } + ok = value.isValid(); + } else { + ok = false; + } + return ok; +} + +bool fromJsonValue(QByteArray &value, const QJsonValue &jval) { + bool ok = true; + if (!jval.isUndefined() && !jval.isNull() && jval.isString()) { + value = QByteArray::fromBase64(QByteArray::fromStdString(jval.toString().toStdString())); + ok = value.size() > 0; + } else { + ok = false; + } + return ok; +} + +bool fromJsonValue(QDate &value, const QJsonValue &jval) { + bool ok = true; + if (!jval.isUndefined() && !jval.isNull() && jval.isString()) { + value = QDate::fromString(jval.toString(), Qt::ISODate); + ok = value.isValid(); + } else { + ok = false; + } + return ok; +} + +bool fromJsonValue(qint32 &value, const QJsonValue &jval) { + bool ok = true; + if (!jval.isUndefined() && !jval.isNull() && !jval.isObject() && !jval.isArray()) { + value = jval.toInt(); + } else { + ok = false; + } + return ok; +} + +bool fromJsonValue(qint64 &value, const QJsonValue &jval) { + bool ok = true; + if (!jval.isUndefined() && !jval.isNull() && !jval.isObject() && !jval.isArray()) { + value = jval.toVariant().toLongLong(); + } else { + ok = false; + } + return ok; +} + +bool fromJsonValue(bool &value, const QJsonValue &jval) { + bool ok = true; + if (jval.isBool()) { + value = jval.toBool(); + } else { + ok = false; + } + return ok; +} + +bool fromJsonValue(float &value, const QJsonValue &jval) { + bool ok = true; + if (jval.isDouble()) { + value = static_cast(jval.toDouble()); + } else { + ok = false; + } + return ok; +} + +bool fromJsonValue(double &value, const QJsonValue &jval) { + bool ok = true; + if (jval.isDouble()) { + value = jval.toDouble(); + } else { + ok = false; + } + return ok; +} + +bool fromJsonValue(OAIObject &value, const QJsonValue &jval) { + bool ok = true; + if (jval.isObject()) { + value.fromJsonObject(jval.toObject()); + ok = value.isValid(); + } else { + ok = false; + } + return ok; +} + +bool fromJsonValue(OAIEnum &value, const QJsonValue &jval) { + value.fromJsonValue(jval); + return true; +} + +bool fromJsonValue(OAIHttpFileElement &value, const QJsonValue &jval) { + return value.fromJsonValue(jval); +} + +} // namespace OpenAPI diff --git a/ext/pdclient/OAIHelpers.h b/ext/pdclient/OAIHelpers.h new file mode 100644 index 000000000..06fe6ff34 --- /dev/null +++ b/ext/pdclient/OAIHelpers.h @@ -0,0 +1,275 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#ifndef OAI_HELPERS_H +#define OAI_HELPERS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "OAIEnum.h" +#include "OAIHttpFileElement.h" +#include "OAIObject.h" + +namespace OpenAPI { + +template +class OptionalParam { +public: + T m_Value; + bool m_hasValue; +public: + OptionalParam(){ + m_hasValue = false; + } + OptionalParam(const T &val){ + m_hasValue = true; + m_Value = val; + } + bool hasValue() const { + return m_hasValue; + } + T value() const{ + return m_Value; + } +}; + +bool setDateTimeFormat(const QString &format); +bool setDateTimeFormat(const Qt::DateFormat &format); + +template +QString toStringValue(const QList &val); + +template +QString toStringValue(const QSet &val); + +template +bool fromStringValue(const QList &inStr, QList &val); + +template +bool fromStringValue(const QSet &inStr, QList &val); + +template +bool fromStringValue(const QMap &inStr, QMap &val); + +template +QJsonValue toJsonValue(const QList &val); + +template +QJsonValue toJsonValue(const QSet &val); + +template +QJsonValue toJsonValue(const QMap &val); + +template +bool fromJsonValue(QList &val, const QJsonValue &jval); + +template +bool fromJsonValue(QSet &val, const QJsonValue &jval); + +template +bool fromJsonValue(QMap &val, const QJsonValue &jval); + +QString toStringValue(const QString &value); +QString toStringValue(const QDateTime &value); +QString toStringValue(const QByteArray &value); +QString toStringValue(const QDate &value); +QString toStringValue(const qint32 &value); +QString toStringValue(const qint64 &value); +QString toStringValue(const bool &value); +QString toStringValue(const float &value); +QString toStringValue(const double &value); +QString toStringValue(const OAIObject &value); +QString toStringValue(const OAIEnum &value); +QString toStringValue(const OAIHttpFileElement &value); + +template +QString toStringValue(const QList &val) { + QString strArray; + for (const auto &item : val) { + strArray.append(toStringValue(item) + ","); + } + if (val.count() > 0) { + strArray.chop(1); + } + return strArray; +} + +template +QString toStringValue(const QSet &val) { + QString strArray; + for (const auto &item : val) { + strArray.append(toStringValue(item) + ","); + } + if (val.count() > 0) { + strArray.chop(1); + } + return strArray; +} + +QJsonValue toJsonValue(const QString &value); +QJsonValue toJsonValue(const QDateTime &value); +QJsonValue toJsonValue(const QByteArray &value); +QJsonValue toJsonValue(const QDate &value); +QJsonValue toJsonValue(const qint32 &value); +QJsonValue toJsonValue(const qint64 &value); +QJsonValue toJsonValue(const bool &value); +QJsonValue toJsonValue(const float &value); +QJsonValue toJsonValue(const double &value); +QJsonValue toJsonValue(const OAIObject &value); +QJsonValue toJsonValue(const OAIEnum &value); +QJsonValue toJsonValue(const OAIHttpFileElement &value); + +template +QJsonValue toJsonValue(const QList &val) { + QJsonArray jArray; + for (const auto &item : val) { + jArray.append(toJsonValue(item)); + } + return jArray; +} + +template +QJsonValue toJsonValue(const QSet &val) { + QJsonArray jArray; + for (const auto &item : val) { + jArray.append(toJsonValue(item)); + } + return jArray; +} + +template +QJsonValue toJsonValue(const QMap &val) { + QJsonObject jObject; + for (const auto &itemkey : val.keys()) { + jObject.insert(itemkey, toJsonValue(val.value(itemkey))); + } + return jObject; +} + +bool fromStringValue(const QString &inStr, QString &value); +bool fromStringValue(const QString &inStr, QDateTime &value); +bool fromStringValue(const QString &inStr, QByteArray &value); +bool fromStringValue(const QString &inStr, QDate &value); +bool fromStringValue(const QString &inStr, qint32 &value); +bool fromStringValue(const QString &inStr, qint64 &value); +bool fromStringValue(const QString &inStr, bool &value); +bool fromStringValue(const QString &inStr, float &value); +bool fromStringValue(const QString &inStr, double &value); +bool fromStringValue(const QString &inStr, OAIObject &value); +bool fromStringValue(const QString &inStr, OAIEnum &value); +bool fromStringValue(const QString &inStr, OAIHttpFileElement &value); + +template +bool fromStringValue(const QList &inStr, QList &val) { + bool ok = (inStr.count() > 0); + for (const auto &item : inStr) { + T itemVal; + ok &= fromStringValue(item, itemVal); + val.push_back(itemVal); + } + return ok; +} + +template +bool fromStringValue(const QSet &inStr, QList &val) { + bool ok = (inStr.count() > 0); + for (const auto &item : inStr) { + T itemVal; + ok &= fromStringValue(item, itemVal); + val.push_back(itemVal); + } + return ok; +} + +template +bool fromStringValue(const QMap &inStr, QMap &val) { + bool ok = (inStr.count() > 0); + for (const auto &itemkey : inStr.keys()) { + T itemVal; + ok &= fromStringValue(inStr.value(itemkey), itemVal); + val.insert(itemkey, itemVal); + } + return ok; +} + +bool fromJsonValue(QString &value, const QJsonValue &jval); +bool fromJsonValue(QDateTime &value, const QJsonValue &jval); +bool fromJsonValue(QByteArray &value, const QJsonValue &jval); +bool fromJsonValue(QDate &value, const QJsonValue &jval); +bool fromJsonValue(qint32 &value, const QJsonValue &jval); +bool fromJsonValue(qint64 &value, const QJsonValue &jval); +bool fromJsonValue(bool &value, const QJsonValue &jval); +bool fromJsonValue(float &value, const QJsonValue &jval); +bool fromJsonValue(double &value, const QJsonValue &jval); +bool fromJsonValue(OAIObject &value, const QJsonValue &jval); +bool fromJsonValue(OAIEnum &value, const QJsonValue &jval); +bool fromJsonValue(OAIHttpFileElement &value, const QJsonValue &jval); + +template +bool fromJsonValue(QList &val, const QJsonValue &jval) { + bool ok = true; + if (jval.isArray()) { + for (const auto jitem : jval.toArray()) { + T item; + ok &= fromJsonValue(item, jitem); + val.push_back(item); + } + } else { + ok = false; + } + return ok; +} + +template +bool fromJsonValue(QSet &val, const QJsonValue &jval) { + bool ok = true; + if (jval.isArray()) { + for (const auto jitem : jval.toArray()) { + T item; + ok &= fromJsonValue(item, jitem); + val.insert(item); + } + } else { + ok = false; + } + return ok; +} + +template +bool fromJsonValue(QMap &val, const QJsonValue &jval) { + bool ok = true; + if (jval.isObject()) { + auto varmap = jval.toObject().toVariantMap(); + if (varmap.count() > 0) { + for (const auto &itemkey : varmap.keys()) { + T itemVal; + ok &= fromJsonValue(itemVal, QJsonValue::fromVariant(varmap.value(itemkey))); + val.insert(itemkey, itemVal); + } + } + } else { + ok = false; + } + return ok; +} + +} // namespace OpenAPI + +#endif // OAI_HELPERS_H diff --git a/ext/pdclient/OAIHttpFileElement.cpp b/ext/pdclient/OAIHttpFileElement.cpp new file mode 100644 index 000000000..b2c6774dd --- /dev/null +++ b/ext/pdclient/OAIHttpFileElement.cpp @@ -0,0 +1,155 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#include +#include +#include +#include + +#include "OAIHttpFileElement.h" + +namespace OpenAPI { + +void OAIHttpFileElement::setMimeType(const QString &mime) { + mime_type = mime; +} + +void OAIHttpFileElement::setFileName(const QString &name) { + local_filename = name; +} + +void OAIHttpFileElement::setVariableName(const QString &name) { + variable_name = name; +} + +void OAIHttpFileElement::setRequestFileName(const QString &name) { + request_filename = name; +} + +bool OAIHttpFileElement::isSet() const { + return !local_filename.isEmpty() || !request_filename.isEmpty(); +} + +QString OAIHttpFileElement::asJson() const { + QFile file(local_filename); + QByteArray bArray; + bool result = false; + if (file.exists()) { + result = file.open(QIODevice::ReadOnly); + bArray = file.readAll(); + file.close(); + } + if (!result) { + qDebug() << "Error opening file " << local_filename; + } + return QString(bArray); +} + +QJsonValue OAIHttpFileElement::asJsonValue() const { + QFile file(local_filename); + QByteArray bArray; + bool result = false; + if (file.exists()) { + result = file.open(QIODevice::ReadOnly); + bArray = file.readAll(); + file.close(); + } + if (!result) { + qDebug() << "Error opening file " << local_filename; + } +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + return QJsonDocument::fromJson(bArray.data()).object(); +#else + return QJsonDocument::fromBinaryData(bArray.data()).object(); +#endif +} + +bool OAIHttpFileElement::fromStringValue(const QString &instr) { + QFile file(local_filename); + bool result = false; + if (file.exists()) { + file.remove(); + } + result = file.open(QIODevice::WriteOnly); + file.write(instr.toUtf8()); + file.close(); + if (!result) { + qDebug() << "Error creating file " << local_filename; + } + return result; +} + +bool OAIHttpFileElement::fromJsonValue(const QJsonValue &jval) { + QFile file(local_filename); + bool result = false; + if (file.exists()) { + file.remove(); + } + result = file.open(QIODevice::WriteOnly); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + file.write(QJsonDocument(jval.toObject()).toJson()); +#else + file.write(QJsonDocument(jval.toObject()).toBinaryData()); +#endif + file.close(); + if (!result) { + qDebug() << "Error creating file " << local_filename; + } + return result; +} + +QByteArray OAIHttpFileElement::asByteArray() const { + QFile file(local_filename); + QByteArray bArray; + bool result = false; + if (file.exists()) { + result = file.open(QIODevice::ReadOnly); + bArray = file.readAll(); + file.close(); + } + if (!result) { + qDebug() << "Error opening file " << local_filename; + } + return bArray; +} + +bool OAIHttpFileElement::fromByteArray(const QByteArray &bytes) { + QFile file(local_filename); + bool result = false; + if (file.exists()) { + file.remove(); + } + result = file.open(QIODevice::WriteOnly); + file.write(bytes); + file.close(); + if (!result) { + qDebug() << "Error creating file " << local_filename; + } + return result; +} + +bool OAIHttpFileElement::saveToFile(const QString &varName, const QString &localFName, const QString &reqFname, const QString &mime, const QByteArray &bytes) { + setMimeType(mime); + setFileName(localFName); + setVariableName(varName); + setRequestFileName(reqFname); + return fromByteArray(bytes); +} + +QByteArray OAIHttpFileElement::loadFromFile(const QString &varName, const QString &localFName, const QString &reqFname, const QString &mime) { + setMimeType(mime); + setFileName(localFName); + setVariableName(varName); + setRequestFileName(reqFname); + return asByteArray(); +} + +} // namespace OpenAPI diff --git a/ext/pdclient/OAIHttpFileElement.h b/ext/pdclient/OAIHttpFileElement.h new file mode 100644 index 000000000..2f59cb8de --- /dev/null +++ b/ext/pdclient/OAIHttpFileElement.h @@ -0,0 +1,47 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#ifndef OAI_HTTP_FILE_ELEMENT_H +#define OAI_HTTP_FILE_ELEMENT_H + +#include +#include +#include + +namespace OpenAPI { + +class OAIHttpFileElement { + +public: + QString variable_name; + QString local_filename; + QString request_filename; + QString mime_type; + void setMimeType(const QString &mime); + void setFileName(const QString &name); + void setVariableName(const QString &name); + void setRequestFileName(const QString &name); + bool isSet() const; + bool fromStringValue(const QString &instr); + bool fromJsonValue(const QJsonValue &jval); + bool fromByteArray(const QByteArray &bytes); + bool saveToFile(const QString &variable_name, const QString &local_filename, const QString &request_filename, const QString &mime, const QByteArray &bytes); + QString asJson() const; + QJsonValue asJsonValue() const; + QByteArray asByteArray() const; + QByteArray loadFromFile(const QString &variable_name, const QString &local_filename, const QString &request_filename, const QString &mime); +}; + +} // namespace OpenAPI + +Q_DECLARE_METATYPE(OpenAPI::OAIHttpFileElement) + +#endif // OAI_HTTP_FILE_ELEMENT_H diff --git a/ext/pdclient/OAIHttpRequest.cpp b/ext/pdclient/OAIHttpRequest.cpp new file mode 100644 index 000000000..dfa70b26f --- /dev/null +++ b/ext/pdclient/OAIHttpRequest.cpp @@ -0,0 +1,505 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + #define SKIP_EMPTY_PARTS Qt::SkipEmptyParts +#else + #define SKIP_EMPTY_PARTS QString::SkipEmptyParts +#endif + +#include "OAIHttpRequest.h" + +namespace OpenAPI { + +OAIHttpRequestInput::OAIHttpRequestInput() { + initialize(); +} + +OAIHttpRequestInput::OAIHttpRequestInput(QString v_url_str, QString v_http_method) { + initialize(); + url_str = v_url_str; + http_method = v_http_method; +} + +void OAIHttpRequestInput::initialize() { + var_layout = NOT_SET; + url_str = ""; + http_method = "GET"; +} + +void OAIHttpRequestInput::add_var(QString key, QString value) { + vars[key] = value; +} + +void OAIHttpRequestInput::add_file(QString variable_name, QString local_filename, QString request_filename, QString mime_type) { + OAIHttpFileElement file; + file.variable_name = variable_name; + file.local_filename = local_filename; + file.request_filename = request_filename; + file.mime_type = mime_type; + files.append(file); +} + +OAIHttpRequestWorker::OAIHttpRequestWorker(QObject *parent, QNetworkAccessManager *_manager) + : QObject(parent), manager(_manager), timeOutTimer(this), isResponseCompressionEnabled(false), isRequestCompressionEnabled(false), httpResponseCode(-1) { + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + randomGenerator = QRandomGenerator(QDateTime::currentDateTime().toSecsSinceEpoch()); +#else + qsrand(QDateTime::currentDateTime().toTime_t()); +#endif + + if (manager == nullptr) { + manager = new QNetworkAccessManager(this); + } + workingDirectory = QDir::currentPath(); + timeOutTimer.setSingleShot(true); +} + +OAIHttpRequestWorker::~OAIHttpRequestWorker() { + QObject::disconnect(&timeOutTimer, &QTimer::timeout, nullptr, nullptr); + timeOutTimer.stop(); + for (const auto &item : multiPartFields) { + if (item != nullptr) { + delete item; + } + } +} + +QMap OAIHttpRequestWorker::getResponseHeaders() const { + return headers; +} + +OAIHttpFileElement OAIHttpRequestWorker::getHttpFileElement(const QString &fieldname) { + if (!files.isEmpty()) { + if (fieldname.isEmpty()) { + return files.first(); + } else if (files.contains(fieldname)) { + return files[fieldname]; + } + } + return OAIHttpFileElement(); +} + +QByteArray *OAIHttpRequestWorker::getMultiPartField(const QString &fieldname) { + if (!multiPartFields.isEmpty()) { + if (fieldname.isEmpty()) { + return multiPartFields.first(); + } else if (multiPartFields.contains(fieldname)) { + return multiPartFields[fieldname]; + } + } + return nullptr; +} + +void OAIHttpRequestWorker::setTimeOut(int timeOutMs) { + timeOutTimer.setInterval(timeOutMs); + if(timeOutTimer.interval() == 0) { + QObject::disconnect(&timeOutTimer, &QTimer::timeout, nullptr, nullptr); + } +} + +void OAIHttpRequestWorker::setWorkingDirectory(const QString &path) { + if (!path.isEmpty()) { + workingDirectory = path; + } +} + +void OAIHttpRequestWorker::setResponseCompressionEnabled(bool enable) { + isResponseCompressionEnabled = enable; +} + +void OAIHttpRequestWorker::setRequestCompressionEnabled(bool enable) { + isRequestCompressionEnabled = enable; +} + +int OAIHttpRequestWorker::getHttpResponseCode() const{ + return httpResponseCode; +} + +QString OAIHttpRequestWorker::http_attribute_encode(QString attribute_name, QString input) { + // result structure follows RFC 5987 + bool need_utf_encoding = false; + QString result = ""; + QByteArray input_c = input.toLocal8Bit(); + char c; + for (int i = 0; i < input_c.length(); i++) { + c = input_c.at(i); + if (c == '\\' || c == '/' || c == '\0' || c < ' ' || c > '~') { + // ignore and request utf-8 version + need_utf_encoding = true; + } else if (c == '"') { + result += "\\\""; + } else { + result += c; + } + } + + if (result.length() == 0) { + need_utf_encoding = true; + } + + if (!need_utf_encoding) { + // return simple version + return QString("%1=\"%2\"").arg(attribute_name, result); + } + + QString result_utf8 = ""; + for (int i = 0; i < input_c.length(); i++) { + c = input_c.at(i); + if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { + result_utf8 += c; + } else { + result_utf8 += "%" + QString::number(static_cast(input_c.at(i)), 16).toUpper(); + } + } + + // return enhanced version with UTF-8 support + return QString("%1=\"%2\"; %1*=utf-8''%3").arg(attribute_name, result, result_utf8); +} + +void OAIHttpRequestWorker::execute(OAIHttpRequestInput *input) { + + // reset variables + QNetworkReply *reply = nullptr; + QByteArray request_content = ""; + response = ""; + error_type = QNetworkReply::NoError; + error_str = ""; + bool isFormData = false; + + // decide on the variable layout + + if (input->files.length() > 0) { + input->var_layout = MULTIPART; + } + if (input->var_layout == NOT_SET) { + input->var_layout = input->http_method == "GET" || input->http_method == "HEAD" ? ADDRESS : URL_ENCODED; + } + + // prepare request content + + QString boundary = ""; + + if (input->var_layout == ADDRESS || input->var_layout == URL_ENCODED) { + // variable layout is ADDRESS or URL_ENCODED + + if (input->vars.count() > 0) { + bool first = true; + isFormData = true; + foreach (QString key, input->vars.keys()) { + if (!first) { + request_content.append("&"); + } + first = false; + + request_content.append(QUrl::toPercentEncoding(key)); + request_content.append("="); + request_content.append(QUrl::toPercentEncoding(input->vars.value(key))); + } + + if (input->var_layout == ADDRESS) { + input->url_str += "?" + request_content; + request_content = ""; + } + } + } else { + // variable layout is MULTIPART + + boundary = QString("__-----------------------%1%2") + #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + .arg(QDateTime::currentDateTime().toSecsSinceEpoch()) + .arg(randomGenerator.generate()); + #else + .arg(QDateTime::currentDateTime().toTime_t()) + .arg(qrand()); + #endif + QString boundary_delimiter = "--"; + QString new_line = "\r\n"; + + // add variables + foreach (QString key, input->vars.keys()) { + // add boundary + request_content.append(boundary_delimiter.toUtf8()); + request_content.append(boundary.toUtf8()); + request_content.append(new_line.toUtf8()); + + // add header + request_content.append("Content-Disposition: form-data; "); + request_content.append(http_attribute_encode("name", key).toUtf8()); + request_content.append(new_line.toUtf8()); + request_content.append("Content-Type: text/plain"); + request_content.append(new_line.toUtf8()); + + // add header to body splitter + request_content.append(new_line.toUtf8()); + + // add variable content + request_content.append(input->vars.value(key).toUtf8()); + request_content.append(new_line.toUtf8()); + } + + // add files + for (QList::iterator file_info = input->files.begin(); file_info != input->files.end(); file_info++) { + QFileInfo fi(file_info->local_filename); + + // ensure necessary variables are available + if (file_info->local_filename == nullptr + || file_info->local_filename.isEmpty() + || file_info->variable_name == nullptr + || file_info->variable_name.isEmpty() + || !fi.exists() + || !fi.isFile() + || !fi.isReadable()) { + // silent abort for the current file + continue; + } + + QFile file(file_info->local_filename); + if (!file.open(QIODevice::ReadOnly)) { + // silent abort for the current file + continue; + } + + // ensure filename for the request + if (file_info->request_filename == nullptr || file_info->request_filename.isEmpty()) { + file_info->request_filename = fi.fileName(); + if (file_info->request_filename.isEmpty()) { + file_info->request_filename = "file"; + } + } + + // add boundary + request_content.append(boundary_delimiter.toUtf8()); + request_content.append(boundary.toUtf8()); + request_content.append(new_line.toUtf8()); + + // add header + request_content.append( + QString("Content-Disposition: form-data; %1; %2").arg(http_attribute_encode("name", file_info->variable_name), http_attribute_encode("filename", file_info->request_filename)).toUtf8()); + request_content.append(new_line.toUtf8()); + + if (file_info->mime_type != nullptr && !file_info->mime_type.isEmpty()) { + request_content.append("Content-Type: "); + request_content.append(file_info->mime_type.toUtf8()); + request_content.append(new_line.toUtf8()); + } + + request_content.append("Content-Transfer-Encoding: binary"); + request_content.append(new_line.toUtf8()); + + // add header to body splitter + request_content.append(new_line.toUtf8()); + + // add file content + request_content.append(file.readAll()); + request_content.append(new_line.toUtf8()); + + file.close(); + } + + // add end of body + request_content.append(boundary_delimiter.toUtf8()); + request_content.append(boundary.toUtf8()); + request_content.append(boundary_delimiter.toUtf8()); + } + + if (input->request_body.size() > 0) { + qDebug() << "got a request body"; + request_content.clear(); + if(!isFormData && (input->var_layout != MULTIPART) && isRequestCompressionEnabled){ + request_content.append(compress(input->request_body, 7, OAICompressionType::Gzip)); + } else { + request_content.append(input->request_body); + } + } + // prepare connection + + QNetworkRequest request = QNetworkRequest(QUrl(input->url_str)); + if (OAIHttpRequestWorker::sslDefaultConfiguration != nullptr) { + request.setSslConfiguration(*OAIHttpRequestWorker::sslDefaultConfiguration); + } + request.setRawHeader("User-Agent", "OpenAPI-Generator/1.0.0/cpp-qt"); + foreach (QString key, input->headers.keys()) { request.setRawHeader(key.toStdString().c_str(), input->headers.value(key).toStdString().c_str()); } + + if (request_content.size() > 0 && !isFormData && (input->var_layout != MULTIPART)) { + if (!input->headers.contains("Content-Type")) { + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + } else { + request.setHeader(QNetworkRequest::ContentTypeHeader, input->headers.value("Content-Type")); + } + if(isRequestCompressionEnabled){ + request.setRawHeader("Content-Encoding", "gzip"); + } + } else if (input->var_layout == URL_ENCODED) { + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + } else if (input->var_layout == MULTIPART) { + request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + boundary); + } + + if(isResponseCompressionEnabled){ + request.setRawHeader("Accept-Encoding", "gzip"); + } else { + request.setRawHeader("Accept-Encoding", "identity"); + } + + if (input->http_method == "GET") { + reply = manager->get(request); + } else if (input->http_method == "POST") { + reply = manager->post(request, request_content); + } else if (input->http_method == "PUT") { + reply = manager->put(request, request_content); + } else if (input->http_method == "HEAD") { + reply = manager->head(request); + } else if (input->http_method == "DELETE") { + reply = manager->deleteResource(request); + } else { +#if (QT_VERSION >= 0x050800) + reply = manager->sendCustomRequest(request, input->http_method.toLatin1(), request_content); +#else + QBuffer *buffer = new QBuffer; + buffer->setData(request_content); + buffer->open(QIODevice::ReadOnly); + + reply = manager->sendCustomRequest(request, input->http_method.toLatin1(), buffer); + buffer->setParent(reply); +#endif + } + if (reply != nullptr) { + reply->setParent(this); + connect(reply, &QNetworkReply::finished, [this, reply] { + on_reply_finished(reply); + }); + } + if (timeOutTimer.interval() > 0) { + QObject::connect(&timeOutTimer, &QTimer::timeout, [this, reply] { + on_reply_timeout(reply); + }); + timeOutTimer.start(); + } +} + +void OAIHttpRequestWorker::on_reply_finished(QNetworkReply *reply) { + bool codeSts = false; + if(timeOutTimer.isActive()) { + QObject::disconnect(&timeOutTimer, &QTimer::timeout, nullptr, nullptr); + timeOutTimer.stop(); + } + error_type = reply->error(); + error_str = reply->errorString(); + if (reply->rawHeaderPairs().count() > 0) { + for (const auto &item : reply->rawHeaderPairs()) { + headers.insert(item.first, item.second); + } + } + auto rescode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&codeSts); + if(codeSts){ + httpResponseCode = rescode; + } else{ + httpResponseCode = -1; + } + process_response(reply); + reply->deleteLater(); + emit on_execution_finished(this); +} + +void OAIHttpRequestWorker::on_reply_timeout(QNetworkReply *reply) { + error_type = QNetworkReply::TimeoutError; + response = ""; + error_str = "Timed out waiting for response"; + disconnect(reply, nullptr, nullptr, nullptr); + reply->abort(); + reply->deleteLater(); + emit on_execution_finished(this); +} + +void OAIHttpRequestWorker::process_response(QNetworkReply *reply) { + QString contentDispositionHdr; + QString contentTypeHdr; + QString contentEncodingHdr; + + for(auto hdr: getResponseHeaders().keys()){ + if(hdr.compare(QString("Content-Disposition"), Qt::CaseInsensitive) == 0){ + contentDispositionHdr = getResponseHeaders().value(hdr); + } + if(hdr.compare(QString("Content-Type"), Qt::CaseInsensitive) == 0){ + contentTypeHdr = getResponseHeaders().value(hdr); + } + if(hdr.compare(QString("Content-Encoding"), Qt::CaseInsensitive) == 0){ + contentEncodingHdr = getResponseHeaders().value(hdr); + } + } + + if (!contentDispositionHdr.isEmpty()) { + auto contentDisposition = contentDispositionHdr.split(QString(";"), SKIP_EMPTY_PARTS); + auto contentType = + !contentTypeHdr.isEmpty() ? contentTypeHdr.split(QString(";"), SKIP_EMPTY_PARTS).first() : QString(); + if ((contentDisposition.count() > 0) && (contentDisposition.first() == QString("attachment"))) { + QString filename = QUuid::createUuid().toString(); + for (const auto &file : contentDisposition) { + if (file.contains(QString("filename"))) { + filename = file.split(QString("="), SKIP_EMPTY_PARTS).at(1); + break; + } + } + OAIHttpFileElement felement; + felement.saveToFile(QString(), workingDirectory + QDir::separator() + filename, filename, contentType, reply->readAll()); + files.insert(filename, felement); + } + + } else if (!contentTypeHdr.isEmpty()) { + auto contentType = contentTypeHdr.split(QString(";"), SKIP_EMPTY_PARTS); + if ((contentType.count() > 0) && (contentType.first() == QString("multipart/form-data"))) { + // TODO : Handle Multipart responses + } else { + if(!contentEncodingHdr.isEmpty()){ + auto encoding = contentEncodingHdr.split(QString(";"), SKIP_EMPTY_PARTS); + if(encoding.count() > 0){ + auto compressionTypes = encoding.first().split(',', SKIP_EMPTY_PARTS); + if(compressionTypes.contains("gzip", Qt::CaseInsensitive) || compressionTypes.contains("deflate", Qt::CaseInsensitive)){ + response = decompress(reply->readAll()); + } else if(compressionTypes.contains("identity", Qt::CaseInsensitive)){ + response = reply->readAll(); + } + } + } + else { + response = reply->readAll(); + } + } + } +} + +QByteArray OAIHttpRequestWorker::decompress(const QByteArray& data){ + + Q_UNUSED(data); + return QByteArray(); +} + +QByteArray OAIHttpRequestWorker::compress(const QByteArray& input, int level, OAICompressionType compressType) { + + Q_UNUSED(input); + Q_UNUSED(level); + Q_UNUSED(compressType); + return QByteArray(); +} + +QSslConfiguration *OAIHttpRequestWorker::sslDefaultConfiguration; + +} // namespace OpenAPI diff --git a/ext/pdclient/OAIHttpRequest.h b/ext/pdclient/OAIHttpRequest.h new file mode 100644 index 000000000..cda089bf2 --- /dev/null +++ b/ext/pdclient/OAIHttpRequest.h @@ -0,0 +1,113 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/** + * Based on http://www.creativepulse.gr/en/blog/2014/restful-api-requests-using-qt-cpp-for-linux-mac-osx-ms-windows + * By Alex Stylianos + * + **/ + +#ifndef OAI_HTTPREQUESTWORKER_H +#define OAI_HTTPREQUESTWORKER_H + +#include +#include +#include +#include +#include +#include +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + #include +#endif + +#include "OAIHttpFileElement.h" + +namespace OpenAPI { + +enum OAIHttpRequestVarLayout { + NOT_SET, + ADDRESS, + URL_ENCODED, + MULTIPART +}; + +class OAIHttpRequestInput { + +public: + QString url_str; + QString http_method; + OAIHttpRequestVarLayout var_layout; + QMap vars; + QMap headers; + QList files; + QByteArray request_body; + + OAIHttpRequestInput(); + OAIHttpRequestInput(QString v_url_str, QString v_http_method); + void initialize(); + void add_var(QString key, QString value); + void add_file(QString variable_name, QString local_filename, QString request_filename, QString mime_type); +}; + +class OAIHttpRequestWorker : public QObject { + Q_OBJECT + +public: + explicit OAIHttpRequestWorker(QObject *parent = nullptr, QNetworkAccessManager *manager = nullptr); + virtual ~OAIHttpRequestWorker(); + + QByteArray response; + QNetworkReply::NetworkError error_type; + QString error_str; + + QMap getResponseHeaders() const; + QString http_attribute_encode(QString attribute_name, QString input); + void execute(OAIHttpRequestInput *input); + static QSslConfiguration *sslDefaultConfiguration; + void setTimeOut(int timeOutMs); + void setWorkingDirectory(const QString &path); + OAIHttpFileElement getHttpFileElement(const QString &fieldname = QString()); + QByteArray *getMultiPartField(const QString &fieldname = QString()); + void setResponseCompressionEnabled(bool enable); + void setRequestCompressionEnabled(bool enable); + int getHttpResponseCode() const; + +signals: + void on_execution_finished(OAIHttpRequestWorker *worker); + +private: + enum OAICompressionType{ + Zlib, + Gzip + }; + QNetworkAccessManager *manager; + QMap headers; + QMap files; + QMap multiPartFields; + QString workingDirectory; + QTimer timeOutTimer; + bool isResponseCompressionEnabled; + bool isRequestCompressionEnabled; + int httpResponseCode; +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + QRandomGenerator randomGenerator; +#endif + + void on_reply_timeout(QNetworkReply *reply); + void on_reply_finished(QNetworkReply *reply); + void process_response(QNetworkReply *reply); + QByteArray decompress(const QByteArray& data); + QByteArray compress(const QByteArray& input, int level, OAICompressionType compressType); +}; + +} // namespace OpenAPI + +#endif // OAI_HTTPREQUESTWORKER_H diff --git a/ext/pdclient/OAIInspectionRequest.cpp b/ext/pdclient/OAIInspectionRequest.cpp new file mode 100644 index 000000000..161d4cdfd --- /dev/null +++ b/ext/pdclient/OAIInspectionRequest.cpp @@ -0,0 +1,160 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#include "OAIInspectionRequest.h" + +#include +#include +#include +#include + +#include "OAIHelpers.h" + +namespace OpenAPI { + +OAIInspectionRequest::OAIInspectionRequest(QString json) { + this->initializeModel(); + this->fromJson(json); +} + +OAIInspectionRequest::OAIInspectionRequest() { + this->initializeModel(); +} + +OAIInspectionRequest::~OAIInspectionRequest() {} + +void OAIInspectionRequest::initializeModel() { + + m_vehicle_id_isSet = false; + m_vehicle_id_isValid = false; + + m_container_id_isSet = false; + m_container_id_isValid = false; + + m_action_id_isSet = false; + m_action_id_isValid = false; +} + +void OAIInspectionRequest::fromJson(QString jsonString) { + QByteArray array(jsonString.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); +} + +void OAIInspectionRequest::fromJsonObject(QJsonObject json) { + + m_vehicle_id_isValid = ::OpenAPI::fromJsonValue(vehicle_id, json[QString("vehicle_id")]); + m_vehicle_id_isSet = !json[QString("vehicle_id")].isNull() && m_vehicle_id_isValid; + + m_container_id_isValid = ::OpenAPI::fromJsonValue(container_id, json[QString("container_id")]); + m_container_id_isSet = !json[QString("container_id")].isNull() && m_container_id_isValid; + + m_action_id_isValid = ::OpenAPI::fromJsonValue(action_id, json[QString("action_id")]); + m_action_id_isSet = !json[QString("action_id")].isNull() && m_action_id_isValid; +} + +QString OAIInspectionRequest::asJson() const { + QJsonObject obj = this->asJsonObject(); + QJsonDocument doc(obj); + QByteArray bytes = doc.toJson(); + return QString(bytes); +} + +QJsonObject OAIInspectionRequest::asJsonObject() const { + QJsonObject obj; + if (m_vehicle_id_isSet) { + obj.insert(QString("vehicle_id"), ::OpenAPI::toJsonValue(vehicle_id)); + } + if (m_container_id_isSet) { + obj.insert(QString("container_id"), ::OpenAPI::toJsonValue(container_id)); + } + if (m_action_id_isSet) { + obj.insert(QString("action_id"), ::OpenAPI::toJsonValue(action_id)); + } + return obj; +} + +QString OAIInspectionRequest::getVehicleId() const { + return vehicle_id; +} +void OAIInspectionRequest::setVehicleId(const QString &vehicle_id) { + this->vehicle_id = vehicle_id; + this->m_vehicle_id_isSet = true; +} + +bool OAIInspectionRequest::is_vehicle_id_Set() const{ + return m_vehicle_id_isSet; +} + +bool OAIInspectionRequest::is_vehicle_id_Valid() const{ + return m_vehicle_id_isValid; +} + +QString OAIInspectionRequest::getContainerId() const { + return container_id; +} +void OAIInspectionRequest::setContainerId(const QString &container_id) { + this->container_id = container_id; + this->m_container_id_isSet = true; +} + +bool OAIInspectionRequest::is_container_id_Set() const{ + return m_container_id_isSet; +} + +bool OAIInspectionRequest::is_container_id_Valid() const{ + return m_container_id_isValid; +} + +QString OAIInspectionRequest::getActionId() const { + return action_id; +} +void OAIInspectionRequest::setActionId(const QString &action_id) { + this->action_id = action_id; + this->m_action_id_isSet = true; +} + +bool OAIInspectionRequest::is_action_id_Set() const{ + return m_action_id_isSet; +} + +bool OAIInspectionRequest::is_action_id_Valid() const{ + return m_action_id_isValid; +} + +bool OAIInspectionRequest::isSet() const { + bool isObjectUpdated = false; + do { + if (m_vehicle_id_isSet) { + isObjectUpdated = true; + break; + } + + if (m_container_id_isSet) { + isObjectUpdated = true; + break; + } + + if (m_action_id_isSet) { + isObjectUpdated = true; + break; + } + } while (false); + return isObjectUpdated; +} + +bool OAIInspectionRequest::isValid() const { + // only required properties are required for the object to be considered valid + return m_vehicle_id_isValid && m_container_id_isValid && m_action_id_isValid && true; +} + +} // namespace OpenAPI diff --git a/ext/pdclient/OAIInspectionRequest.h b/ext/pdclient/OAIInspectionRequest.h new file mode 100644 index 000000000..2270d3c18 --- /dev/null +++ b/ext/pdclient/OAIInspectionRequest.h @@ -0,0 +1,79 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * OAIInspectionRequest.h + * + * + */ + +#ifndef OAIInspectionRequest_H +#define OAIInspectionRequest_H + +#include + +#include + +#include "OAIEnum.h" +#include "OAIObject.h" + +namespace OpenAPI { + +class OAIInspectionRequest : public OAIObject { +public: + OAIInspectionRequest(); + OAIInspectionRequest(QString json); + ~OAIInspectionRequest() override; + + QString asJson() const override; + QJsonObject asJsonObject() const override; + void fromJsonObject(QJsonObject json) override; + void fromJson(QString jsonString) override; + + QString getVehicleId() const; + void setVehicleId(const QString &vehicle_id); + bool is_vehicle_id_Set() const; + bool is_vehicle_id_Valid() const; + + QString getContainerId() const; + void setContainerId(const QString &container_id); + bool is_container_id_Set() const; + bool is_container_id_Valid() const; + + QString getActionId() const; + void setActionId(const QString &action_id); + bool is_action_id_Set() const; + bool is_action_id_Valid() const; + + virtual bool isSet() const override; + virtual bool isValid() const override; + +private: + void initializeModel(); + + QString vehicle_id; + bool m_vehicle_id_isSet; + bool m_vehicle_id_isValid; + + QString container_id; + bool m_container_id_isSet; + bool m_container_id_isValid; + + QString action_id; + bool m_action_id_isSet; + bool m_action_id_isValid; +}; + +} // namespace OpenAPI + +Q_DECLARE_METATYPE(OpenAPI::OAIInspectionRequest) + +#endif // OAIInspectionRequest_H diff --git a/ext/pdclient/OAIInspectionStatus.cpp b/ext/pdclient/OAIInspectionStatus.cpp new file mode 100644 index 000000000..101fd0a41 --- /dev/null +++ b/ext/pdclient/OAIInspectionStatus.cpp @@ -0,0 +1,250 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#include "OAIInspectionStatus.h" + +#include +#include +#include +#include + +#include "OAIHelpers.h" + +namespace OpenAPI { + +OAIInspectionStatus::OAIInspectionStatus(QString json) { + this->initializeModel(); + this->fromJson(json); +} + +OAIInspectionStatus::OAIInspectionStatus() { + this->initializeModel(); +} + +OAIInspectionStatus::~OAIInspectionStatus() {} + +void OAIInspectionStatus::initializeModel() { + + m_vehicle_id_isSet = false; + m_vehicle_id_isValid = false; + + m_container_id_isSet = false; + m_container_id_isValid = false; + + m_action_id_isSet = false; + m_action_id_isValid = false; + + m_status_isSet = false; + m_status_isValid = false; + + m_requested_isSet = false; + m_requested_isValid = false; + + m_completed_isSet = false; + m_completed_isValid = false; +} + +void OAIInspectionStatus::fromJson(QString jsonString) { + QByteArray array(jsonString.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); +} + +void OAIInspectionStatus::fromJsonObject(QJsonObject json) { + + m_vehicle_id_isValid = ::OpenAPI::fromJsonValue(vehicle_id, json[QString("vehicle_id")]); + m_vehicle_id_isSet = !json[QString("vehicle_id")].isNull() && m_vehicle_id_isValid; + + m_container_id_isValid = ::OpenAPI::fromJsonValue(container_id, json[QString("container_id")]); + m_container_id_isSet = !json[QString("container_id")].isNull() && m_container_id_isValid; + + m_action_id_isValid = ::OpenAPI::fromJsonValue(action_id, json[QString("action_id")]); + m_action_id_isSet = !json[QString("action_id")].isNull() && m_action_id_isValid; + + m_status_isValid = ::OpenAPI::fromJsonValue(status, json[QString("status")]); + m_status_isSet = !json[QString("status")].isNull() && m_status_isValid; + + m_requested_isValid = ::OpenAPI::fromJsonValue(requested, json[QString("requested")]); + m_requested_isSet = !json[QString("requested")].isNull() && m_requested_isValid; + + m_completed_isValid = ::OpenAPI::fromJsonValue(completed, json[QString("completed")]); + m_completed_isSet = !json[QString("completed")].isNull() && m_completed_isValid; +} + +QString OAIInspectionStatus::asJson() const { + QJsonObject obj = this->asJsonObject(); + QJsonDocument doc(obj); + QByteArray bytes = doc.toJson(); + return QString(bytes); +} + +QJsonObject OAIInspectionStatus::asJsonObject() const { + QJsonObject obj; + if (m_vehicle_id_isSet) { + obj.insert(QString("vehicle_id"), ::OpenAPI::toJsonValue(vehicle_id)); + } + if (m_container_id_isSet) { + obj.insert(QString("container_id"), ::OpenAPI::toJsonValue(container_id)); + } + if (m_action_id_isSet) { + obj.insert(QString("action_id"), ::OpenAPI::toJsonValue(action_id)); + } + if (m_status_isSet) { + obj.insert(QString("status"), ::OpenAPI::toJsonValue(status)); + } + if (m_requested_isSet) { + obj.insert(QString("requested"), ::OpenAPI::toJsonValue(requested)); + } + if (m_completed_isSet) { + obj.insert(QString("completed"), ::OpenAPI::toJsonValue(completed)); + } + return obj; +} + +QString OAIInspectionStatus::getVehicleId() const { + return vehicle_id; +} +void OAIInspectionStatus::setVehicleId(const QString &vehicle_id) { + this->vehicle_id = vehicle_id; + this->m_vehicle_id_isSet = true; +} + +bool OAIInspectionStatus::is_vehicle_id_Set() const{ + return m_vehicle_id_isSet; +} + +bool OAIInspectionStatus::is_vehicle_id_Valid() const{ + return m_vehicle_id_isValid; +} + +QString OAIInspectionStatus::getContainerId() const { + return container_id; +} +void OAIInspectionStatus::setContainerId(const QString &container_id) { + this->container_id = container_id; + this->m_container_id_isSet = true; +} + +bool OAIInspectionStatus::is_container_id_Set() const{ + return m_container_id_isSet; +} + +bool OAIInspectionStatus::is_container_id_Valid() const{ + return m_container_id_isValid; +} + +QString OAIInspectionStatus::getActionId() const { + return action_id; +} +void OAIInspectionStatus::setActionId(const QString &action_id) { + this->action_id = action_id; + this->m_action_id_isSet = true; +} + +bool OAIInspectionStatus::is_action_id_Set() const{ + return m_action_id_isSet; +} + +bool OAIInspectionStatus::is_action_id_Valid() const{ + return m_action_id_isValid; +} + +QString OAIInspectionStatus::getStatus() const { + return status; +} +void OAIInspectionStatus::setStatus(const QString &status) { + this->status = status; + this->m_status_isSet = true; +} + +bool OAIInspectionStatus::is_status_Set() const{ + return m_status_isSet; +} + +bool OAIInspectionStatus::is_status_Valid() const{ + return m_status_isValid; +} + +qint64 OAIInspectionStatus::getRequested() const { + return requested; +} +void OAIInspectionStatus::setRequested(const qint64 &requested) { + this->requested = requested; + this->m_requested_isSet = true; +} + +bool OAIInspectionStatus::is_requested_Set() const{ + return m_requested_isSet; +} + +bool OAIInspectionStatus::is_requested_Valid() const{ + return m_requested_isValid; +} + +qint64 OAIInspectionStatus::getCompleted() const { + return completed; +} +void OAIInspectionStatus::setCompleted(const qint64 &completed) { + this->completed = completed; + this->m_completed_isSet = true; +} + +bool OAIInspectionStatus::is_completed_Set() const{ + return m_completed_isSet; +} + +bool OAIInspectionStatus::is_completed_Valid() const{ + return m_completed_isValid; +} + +bool OAIInspectionStatus::isSet() const { + bool isObjectUpdated = false; + do { + if (m_vehicle_id_isSet) { + isObjectUpdated = true; + break; + } + + if (m_container_id_isSet) { + isObjectUpdated = true; + break; + } + + if (m_action_id_isSet) { + isObjectUpdated = true; + break; + } + + if (m_status_isSet) { + isObjectUpdated = true; + break; + } + + if (m_requested_isSet) { + isObjectUpdated = true; + break; + } + + if (m_completed_isSet) { + isObjectUpdated = true; + break; + } + } while (false); + return isObjectUpdated; +} + +bool OAIInspectionStatus::isValid() const { + // only required properties are required for the object to be considered valid + return m_vehicle_id_isValid && m_container_id_isValid && m_action_id_isValid && m_status_isValid && m_requested_isValid && true; +} + +} // namespace OpenAPI diff --git a/ext/pdclient/OAIInspectionStatus.h b/ext/pdclient/OAIInspectionStatus.h new file mode 100644 index 000000000..aee5d535d --- /dev/null +++ b/ext/pdclient/OAIInspectionStatus.h @@ -0,0 +1,106 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * OAIInspectionStatus.h + * + * + */ + +#ifndef OAIInspectionStatus_H +#define OAIInspectionStatus_H + +#include + +#include + +#include "OAIEnum.h" +#include "OAIObject.h" + +namespace OpenAPI { + +class OAIInspectionStatus : public OAIObject { +public: + OAIInspectionStatus(); + OAIInspectionStatus(QString json); + ~OAIInspectionStatus() override; + + QString asJson() const override; + QJsonObject asJsonObject() const override; + void fromJsonObject(QJsonObject json) override; + void fromJson(QString jsonString) override; + + QString getVehicleId() const; + void setVehicleId(const QString &vehicle_id); + bool is_vehicle_id_Set() const; + bool is_vehicle_id_Valid() const; + + QString getContainerId() const; + void setContainerId(const QString &container_id); + bool is_container_id_Set() const; + bool is_container_id_Valid() const; + + QString getActionId() const; + void setActionId(const QString &action_id); + bool is_action_id_Set() const; + bool is_action_id_Valid() const; + + QString getStatus() const; + void setStatus(const QString &status); + bool is_status_Set() const; + bool is_status_Valid() const; + + qint64 getRequested() const; + void setRequested(const qint64 &requested); + bool is_requested_Set() const; + bool is_requested_Valid() const; + + qint64 getCompleted() const; + void setCompleted(const qint64 &completed); + bool is_completed_Set() const; + bool is_completed_Valid() const; + + virtual bool isSet() const override; + virtual bool isValid() const override; + +private: + void initializeModel(); + + QString vehicle_id; + bool m_vehicle_id_isSet; + bool m_vehicle_id_isValid; + + QString container_id; + bool m_container_id_isSet; + bool m_container_id_isValid; + + QString action_id; + bool m_action_id_isSet; + bool m_action_id_isValid; + + QString status; + bool m_status_isSet; + bool m_status_isValid; + + qint64 requested; + bool m_requested_isSet; + bool m_requested_isValid; + + qint64 completed; + bool m_completed_isSet; + bool m_completed_isValid; +}; + +} // namespace OpenAPI + +Q_DECLARE_METATYPE(OpenAPI::OAIInspectionStatus) + +#endif // OAIInspectionStatus_H diff --git a/ext/pdclient/OAIInspectionStatusList.cpp b/ext/pdclient/OAIInspectionStatusList.cpp new file mode 100644 index 000000000..7145b1dd1 --- /dev/null +++ b/ext/pdclient/OAIInspectionStatusList.cpp @@ -0,0 +1,100 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#include "OAIInspectionStatusList.h" + +#include +#include +#include +#include + +#include "OAIHelpers.h" + +namespace OpenAPI { + +OAIInspectionStatusList::OAIInspectionStatusList(QString json) { + this->initializeModel(); + this->fromJson(json); +} + +OAIInspectionStatusList::OAIInspectionStatusList() { + this->initializeModel(); +} + +OAIInspectionStatusList::~OAIInspectionStatusList() {} + +void OAIInspectionStatusList::initializeModel() { + + m_inspections_isSet = false; + m_inspections_isValid = false; +} + +void OAIInspectionStatusList::fromJson(QString jsonString) { + QByteArray array(jsonString.toStdString().c_str()); + QJsonDocument doc = QJsonDocument::fromJson(array); + QJsonObject jsonObject = doc.object(); + this->fromJsonObject(jsonObject); +} + +void OAIInspectionStatusList::fromJsonObject(QJsonObject json) { + + m_inspections_isValid = ::OpenAPI::fromJsonValue(inspections, json[QString("inspections")]); + m_inspections_isSet = !json[QString("inspections")].isNull() && m_inspections_isValid; +} + +QString OAIInspectionStatusList::asJson() const { + QJsonObject obj = this->asJsonObject(); + QJsonDocument doc(obj); + QByteArray bytes = doc.toJson(); + return QString(bytes); +} + +QJsonObject OAIInspectionStatusList::asJsonObject() const { + QJsonObject obj; + if (inspections.size() > 0) { + obj.insert(QString("inspections"), ::OpenAPI::toJsonValue(inspections)); + } + return obj; +} + +QList OAIInspectionStatusList::getInspections() const { + return inspections; +} +void OAIInspectionStatusList::setInspections(const QList &inspections) { + this->inspections = inspections; + this->m_inspections_isSet = true; +} + +bool OAIInspectionStatusList::is_inspections_Set() const{ + return m_inspections_isSet; +} + +bool OAIInspectionStatusList::is_inspections_Valid() const{ + return m_inspections_isValid; +} + +bool OAIInspectionStatusList::isSet() const { + bool isObjectUpdated = false; + do { + if (inspections.size() > 0) { + isObjectUpdated = true; + break; + } + } while (false); + return isObjectUpdated; +} + +bool OAIInspectionStatusList::isValid() const { + // only required properties are required for the object to be considered valid + return true; +} + +} // namespace OpenAPI diff --git a/ext/pdclient/OAIInspectionStatusList.h b/ext/pdclient/OAIInspectionStatusList.h new file mode 100644 index 000000000..8849ffcf5 --- /dev/null +++ b/ext/pdclient/OAIInspectionStatusList.h @@ -0,0 +1,62 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/* + * OAIInspectionStatusList.h + * + * + */ + +#ifndef OAIInspectionStatusList_H +#define OAIInspectionStatusList_H + +#include + +#include "OAIInspectionStatus.h" +#include + +#include "OAIEnum.h" +#include "OAIObject.h" + +namespace OpenAPI { + +class OAIInspectionStatusList : public OAIObject { +public: + OAIInspectionStatusList(); + OAIInspectionStatusList(QString json); + ~OAIInspectionStatusList() override; + + QString asJson() const override; + QJsonObject asJsonObject() const override; + void fromJsonObject(QJsonObject json) override; + void fromJson(QString jsonString) override; + + QList getInspections() const; + void setInspections(const QList &inspections); + bool is_inspections_Set() const; + bool is_inspections_Valid() const; + + virtual bool isSet() const override; + virtual bool isValid() const override; + +private: + void initializeModel(); + + QList inspections; + bool m_inspections_isSet; + bool m_inspections_isValid; +}; + +} // namespace OpenAPI + +Q_DECLARE_METATYPE(OpenAPI::OAIInspectionStatusList) + +#endif // OAIInspectionStatusList_H diff --git a/ext/pdclient/OAIObject.h b/ext/pdclient/OAIObject.h new file mode 100644 index 000000000..68e114afe --- /dev/null +++ b/ext/pdclient/OAIObject.h @@ -0,0 +1,65 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +#ifndef OAI_OBJECT_H +#define OAI_OBJECT_H + +#include +#include +#include + +namespace OpenAPI { + +class OAIObject { +public: + OAIObject() {} + + OAIObject(QString jsonString) { + fromJson(jsonString); + } + + virtual ~OAIObject() {} + + virtual QJsonObject asJsonObject() const { + return jObj; + } + + virtual QString asJson() const { + QJsonDocument doc(jObj); + return doc.toJson(QJsonDocument::Compact); + } + + virtual void fromJson(QString jsonString) { + QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8()); + jObj = doc.object(); + } + + virtual void fromJsonObject(QJsonObject json) { + jObj = json; + } + + virtual bool isSet() const { + return false; + } + + virtual bool isValid() const { + return true; + } + +private: + QJsonObject jObj; +}; + +} // namespace OpenAPI + +Q_DECLARE_METATYPE(OpenAPI::OAIObject) + +#endif // OAI_OBJECT_H diff --git a/ext/pdclient/OAIServerConfiguration.h b/ext/pdclient/OAIServerConfiguration.h new file mode 100644 index 000000000..8d33862a8 --- /dev/null +++ b/ext/pdclient/OAIServerConfiguration.h @@ -0,0 +1,82 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/** + * Representing a Server configuration. + */ +#ifndef OAI_SERVERVCONFIGURATION_H +#define OAI_SERVERVCONFIGURATION_H + +#include +#include +#include +#include +#include +#include "OAIServerVariable.h" + +namespace OpenAPI { + +class OAIServerConfiguration { +public: + /** + * @param url A URL to the target host. + * @param description A description of the host designated by the URL. + * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. + */ + OAIServerConfiguration(const QUrl &url, const QString &description, const QMap &variables) + : _description(description), + _variables(variables), + _url(url){} + OAIServerConfiguration(){} + ~OAIServerConfiguration(){} + + /** + * Format URL template using given variables. + * + * @param variables A map between a variable name and its value. + * @return Formatted URL. + */ + QString URL() { + QString url = _url.toString(); + if(!_variables.empty()){ + // go through variables and replace placeholders + for (auto const& v : _variables.keys()) { + QString name = v; + OAIServerVariable serverVariable = _variables.value(v); + QString value = serverVariable._defaultValue; + + if (!serverVariable._enumValues.empty() && !serverVariable._enumValues.contains(value)) { + throw std::runtime_error(QString("The variable " + name + " in the server URL has invalid value " + value + ".").toUtf8()); + } + QRegularExpression regex(QString("\\{" + name + "\\}")); + url = url.replace(regex, value); + + } + return url; + } + return url; + } + + int setDefaultValue(const QString &variable,const QString &value){ + if(_variables.contains(variable)) + return _variables[variable].setDefaultValue(value); + return -1; + } + + QString _description; + QMap _variables; + QUrl _url; + +}; + +} // namespace OpenAPI + +#endif // OAI_SERVERVCONFIGURATION_H diff --git a/ext/pdclient/OAIServerVariable.h b/ext/pdclient/OAIServerVariable.h new file mode 100644 index 000000000..9930343ca --- /dev/null +++ b/ext/pdclient/OAIServerVariable.h @@ -0,0 +1,58 @@ +/** + * Port Drayage Web Service. + * Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + * + * The version of the OpenAPI document: 1.0 + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/** + * Representing a Server Variable for server URL template substitution. + */ +#ifndef OAI_SERVERVARIABLE_H +#define OAI_SERVERVARIABLE_H +#include +#include + +namespace OpenAPI { + +class OAIServerVariable { +public: + + /** + * @param description A description for the server variable. + * @param defaultValue The default value to use for substitution. + * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. + */ + OAIServerVariable(const QString &description, const QString &defaultValue, const QSet &enumValues) + : _defaultValue(defaultValue), + _description(description), + _enumValues(enumValues){} + + OAIServerVariable(){} + ~OAIServerVariable(){} + + int setDefaultValue(const QString& value){ + if( _enumValues.contains(value)){ + _defaultValue = value; + return 0; + } + return -2; + } + + QString getDefaultValue(){return _defaultValue;} + QSet getEnumValues(){return _enumValues;} + + + QString _defaultValue; + QString _description; + QSet _enumValues; + +}; + +} // namespace OpenAPI + +#endif // OAI_SERVERVARIABLE_H diff --git a/ext/pdclient/client.pri b/ext/pdclient/client.pri new file mode 100644 index 000000000..1a7c42bf9 --- /dev/null +++ b/ext/pdclient/client.pri @@ -0,0 +1,35 @@ +QT += network + +HEADERS += \ +# Models + $${PWD}/OAIActionStatusList.h \ + $${PWD}/OAIContainerActionStatus.h \ + $${PWD}/OAIContainerRequest.h \ + $${PWD}/OAIInspectionRequest.h \ + $${PWD}/OAIInspectionStatus.h \ + $${PWD}/OAIInspectionStatusList.h \ +# APIs + $${PWD}/OAIDefaultApi.h \ +# Others + $${PWD}/OAIHelpers.h \ + $${PWD}/OAIHttpRequest.h \ + $${PWD}/OAIObject.h \ + $${PWD}/OAIEnum.h \ + $${PWD}/OAIHttpFileElement.h \ + $${PWD}/OAIServerConfiguration.h \ + $${PWD}/OAIServerVariable.h + +SOURCES += \ +# Models + $${PWD}/OAIActionStatusList.cpp \ + $${PWD}/OAIContainerActionStatus.cpp \ + $${PWD}/OAIContainerRequest.cpp \ + $${PWD}/OAIInspectionRequest.cpp \ + $${PWD}/OAIInspectionStatus.cpp \ + $${PWD}/OAIInspectionStatusList.cpp \ +# APIs + $${PWD}/OAIDefaultApi.cpp \ +# Others + $${PWD}/OAIHelpers.cpp \ + $${PWD}/OAIHttpRequest.cpp \ + $${PWD}/OAIHttpFileElement.cpp diff --git a/src/tmx/TmxApi/tmx/j2735_messages/J2735MessageFactory.hpp b/src/tmx/TmxApi/tmx/j2735_messages/J2735MessageFactory.hpp index cc75299a6..88609ec81 100644 --- a/src/tmx/TmxApi/tmx/j2735_messages/J2735MessageFactory.hpp +++ b/src/tmx/TmxApi/tmx/j2735_messages/J2735MessageFactory.hpp @@ -340,7 +340,6 @@ class J2735MessageFactory int msgIdindex=0; // msgId = DD if (bytes[0] == 0x00) { - std::cout<<"No Extended bytes found\n"; return 0; } if(bytes[0] == 0x03){ // extended bytes present @@ -354,7 +353,6 @@ class J2735MessageFactory else // 64 < length < 128 bytes [0380XX00DD] msgIdindex = 3; } - std::cout<<"Extended bytes found\n"; } bytes.erase(bytes.begin(),bytes.begin()+msgIdindex); diff --git a/src/tmx/TmxCore/src/ivpcore.cpp b/src/tmx/TmxCore/src/ivpcore.cpp index 50dd49d96..84eb3cf8f 100644 --- a/src/tmx/TmxCore/src/ivpcore.cpp +++ b/src/tmx/TmxCore/src/ivpcore.cpp @@ -133,7 +133,7 @@ std::string GetPwd(){ pwd = std::getenv(EnvVar); if(pwd == NULL){ - LOG_ERROR("Unable to set MYSQL_ROOT_PASSWORD)"); + LOG_ERROR("Unable to set MYSQL_PASSWORD)"); return ""; } else{ diff --git a/src/tmx/TmxCtl/src/lib/PluginConfig.cpp b/src/tmx/TmxCtl/src/lib/PluginConfig.cpp index ca80c112c..888546b99 100644 --- a/src/tmx/TmxCtl/src/lib/PluginConfig.cpp +++ b/src/tmx/TmxCtl/src/lib/PluginConfig.cpp @@ -525,19 +525,5 @@ bool TmxControl::remove(pluginlist &plugins, ...) } -// static std::string TmxControl::GetPwd(){ -// const char* EnvVar = "MYSQL_ROOT_PASSWORD"; -// const char* psw; -// psw = std::getenv(EnvVar); - -// if(psw == NULL){ -// PLOG(logERROR) << "Unable to set MYSQL_ROOT_PASSWORD)"; -// return ""; -// } -// else{ -// std::string PswStr(psw); -// return PswStr; -// } -// } } /* namespace tmxctl */ diff --git a/src/tmx/TmxCtl/src/lib/PluginStatus.cpp b/src/tmx/TmxCtl/src/lib/PluginStatus.cpp index 28bbb0bb3..1d12472ba 100644 --- a/src/tmx/TmxCtl/src/lib/PluginStatus.cpp +++ b/src/tmx/TmxCtl/src/lib/PluginStatus.cpp @@ -87,7 +87,8 @@ bool TmxControl::list(pluginlist &plugins, ...) _output.get_storage().get_tree().clear(); - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->prepareStatement(query)); for (size_t i = 0; i < plugins.size(); i++) @@ -173,7 +174,8 @@ bool TmxControl::state(pluginlist &plugins, ...) PLOG(logDEBUG) << "Executing query " << query; _output.get_storage().get_tree().clear(); - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->prepareStatement(query)); for (size_t i = 0; i < plugins.size(); i++) { @@ -215,7 +217,8 @@ bool TmxControl::max_message_interval(pluginlist &plugins, ...) PLOG(logDEBUG1) << "Executing query (?1 = " << val << ")" << query; - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->prepareStatement(query)); stmt->setString(1, val); for (size_t i = 0; i < plugins.size(); i++) @@ -269,7 +272,8 @@ bool TmxControl::args(pluginlist &plugins, ...) { PLOG(logDEBUG1) << "Executing query (?1 = " << val << ")" << query; - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->prepareStatement(query)); stmt->setString(1, val); for (size_t i = 0; i < plugins.size(); i++) @@ -298,7 +302,8 @@ bool TmxControl::messages(pluginlist &plugins, ...) _output.get_storage().get_tree().clear(); - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->prepareStatement(query)); for (size_t i = 0; i < plugins.size(); i++) @@ -380,7 +385,8 @@ bool TmxControl::events(pluginlist &, ...) _output.get_storage().get_tree().clear(); - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->prepareStatement(query)); @@ -434,7 +440,8 @@ bool TmxControl::system_config(pluginlist &, ...) _output.get_storage().get_tree().clear(); - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->createStatement()); unique_ptr rs(stmt->executeQuery(query)); @@ -476,7 +483,8 @@ bool TmxControl::clear_event_log(pluginlist &, ...) _output.get_storage().get_tree().clear(); - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->prepareStatement(query)); stmt->executeUpdate(); //unique_ptr stmt(conn.Get()->createStatement()); @@ -511,7 +519,8 @@ bool TmxControl::user_info(bool showPassword) _output.get_storage().get_tree().clear(); - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->prepareStatement(query)); stmt->setString(1, (*_opts)["username"].as()); unique_ptr rs(stmt->executeQuery()); @@ -566,7 +575,8 @@ bool TmxControl::all_users_info(bool showPassword) _output.get_storage().get_tree().clear(); - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->createStatement()); unique_ptr rs(stmt->executeQuery(query)); @@ -631,7 +641,8 @@ bool TmxControl::user_add() PLOG(logDEBUG1) << "Executing query (?1 = " << username << ", ?2 = " << password << ", ?3 = " << access_level << ", ?4 = " << username << "): " << query; - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->prepareStatement(query)); stmt.reset(conn.Get()->prepareStatement(query)); stmt->setString(1, username); @@ -699,7 +710,8 @@ bool TmxControl::user_update() query += " WHERE username = ?"; PLOG(logDEBUG1) << "Executing query : " << query; - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->prepareStatement(query)); if (havePassword) { @@ -754,7 +766,8 @@ bool TmxControl::user_delete() _output.get_storage().get_tree().clear(); - DbConnection conn = _pool.Connection(); + std::string pwd = _pool.GetPwd(); + DbConnection conn = _pool.Connection("tcp://127.0.0.1:3306","IVP", pwd, "IVP"); unique_ptr stmt(conn.Get()->prepareStatement(query)); stmt->setString(1, (*_opts)["username"].as()); int deleted = stmt->executeUpdate(); diff --git a/src/tmx/TmxCtl/src/lib/TmxControl.h b/src/tmx/TmxCtl/src/lib/TmxControl.h index 2c65e1b94..77169d205 100644 --- a/src/tmx/TmxCtl/src/lib/TmxControl.h +++ b/src/tmx/TmxCtl/src/lib/TmxControl.h @@ -88,8 +88,7 @@ class TmxControl: public tmx::utils::Runnable { void DisablePermissionCheck(); std::string GetOutput(TmxControlOutputFormat format, bool pretty); tmx::message_container_type* GetOutput(); - // Method for getting credentials - // std::string GetPwd(); + private: boost::program_options::variables_map *_opts; diff --git a/src/tmx/TmxUtils/src/Logger.h b/src/tmx/TmxUtils/src/Logger.h index 855146577..51c3af4f3 100644 --- a/src/tmx/TmxUtils/src/Logger.h +++ b/src/tmx/TmxUtils/src/Logger.h @@ -9,11 +9,11 @@ #define SRC_LOGGER_H_ #ifndef LOGGER_MAX_LEVEL -#define LOGGER_MAX_LEVEL tmx::utils::logERROR +#define LOGGER_MAX_LEVEL tmx::utils::logDEBUG4 #endif #ifndef DEFAULT_LOG_LEVEL -#define DEFAULT_LOG_LEVEL "DEBUG" +#define DEFAULT_LOG_LEVEL "ERROR" #endif #define UNKNOWN_SOURCE "Unknown source" diff --git a/src/v2i-hub/DsrcImmediateForwardPlugin/manifest.json b/src/v2i-hub/DsrcImmediateForwardPlugin/manifest.json index 3df6dee0d..a41ddf97a 100644 --- a/src/v2i-hub/DsrcImmediateForwardPlugin/manifest.json +++ b/src/v2i-hub/DsrcImmediateForwardPlugin/manifest.json @@ -9,7 +9,7 @@ "configuration": [ { "key": "Messages_Destination_1", - "default": "{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"PSM\", \"SendType\": \"PSM\", \"PSID\": \"0x8002\" } ,{ \"TmxType\": \"TMSG07\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\" }] }", + "default": "{ \"Messages\": [ { \"TmxType\": \"SPAT-P\", \"SendType\": \"SPAT\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"MAP-P\", \"SendType\": \"MAP\", \"PSID\": \"0x8002\" }, { \"TmxType\": \"PSM\", \"SendType\": \"PSM\", \"PSID\": \"0x8002\" } ,{ \"TmxType\": \"TMSG07\", \"SendType\": \"TMSG07\", \"PSID\": \"0x8002\" },{ \"TmxType\": \"TMSG03-P\", \"SendType\": \"TMSG03-P\", \"PSID\": \"0xBFEE\" }] }", "description": "JSON data defining the message types and PSIDs for messages forwarded to the DSRC radio at destination 1." }, { diff --git a/src/v2i-hub/DsrcImmediateForwardPlugin/src/DsrcMessageManagerPlugin.cpp b/src/v2i-hub/DsrcImmediateForwardPlugin/src/DsrcMessageManagerPlugin.cpp index d39303618..6406445b7 100644 --- a/src/v2i-hub/DsrcImmediateForwardPlugin/src/DsrcMessageManagerPlugin.cpp +++ b/src/v2i-hub/DsrcImmediateForwardPlugin/src/DsrcMessageManagerPlugin.cpp @@ -90,7 +90,8 @@ void DsrcMessageManagerPlugin::OnMessageReceived(IvpMessage *msg) { // Uncomment this line to call the base method, which prints the message received to cout. //PluginClient::OnMessageReceived(msg); - + PLOG(logDEBUG) << "Message Received " << + "Type: " << msg->type << ", Subtype: " << msg->subtype; if (!_configRead) { PLOG(logWARNING) << "Config not read yet. Message Ignored: " << diff --git a/src/v2i-hub/MobilityOperationPlugin/CMakeLists.txt b/src/v2i-hub/MobilityOperationPlugin/CMakeLists.txt deleted file mode 100644 index bb2ae8805..000000000 --- a/src/v2i-hub/MobilityOperationPlugin/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -PROJECT ( MobilityOperationPlugin VERSION 5.0 LANGUAGES CXX ) - -BuildTmxPlugin ( ) - -TARGET_LINK_LIBRARIES (${PROJECT_NAME} tmxutils) \ No newline at end of file diff --git a/src/v2i-hub/MobilityOperationPlugin/manifest.json b/src/v2i-hub/MobilityOperationPlugin/manifest.json deleted file mode 100644 index 87f553c28..000000000 --- a/src/v2i-hub/MobilityOperationPlugin/manifest.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name":"MobilityOperationPlugin", - "description":"...", - "version":"@PROJECT_VERSION@", - "exeLocation":"/bin/MobilityOperationPlugin", - "coreIpAddr":"127.0.0.1", - "corePort":24601, - "messageTypes":[ - { - "type":"J2735", - "subtype":"TMSG03-P", - "description":"In development" - } - ], - "configuration":[ - { - "key":"...", - "default":"...", - "description":"..." - } - - ] -} diff --git a/src/v2i-hub/MobilityOperationPlugin/src/MobilityOperationPlugin.cpp b/src/v2i-hub/MobilityOperationPlugin/src/MobilityOperationPlugin.cpp deleted file mode 100644 index e445d6c11..000000000 --- a/src/v2i-hub/MobilityOperationPlugin/src/MobilityOperationPlugin.cpp +++ /dev/null @@ -1,86 +0,0 @@ -//============================================================================ -// Name : MobilityOperationPlugin.cpp -// Author : Paul Bourelly -// Version : 5.0 -// Copyright : Your copyright notice -// Description : Hello World in C++, Ansi-style -//============================================================================ - -#include "MobilityOperationPlugin.h" - - -namespace MobilityOperationPlugin { - - - -/** - * Construct a new MobililtyOperationPlugin with the given name. - * - * @param name The name to give the plugin for identification purposes - */ -MobilityOperationPlugin::MobilityOperationPlugin(string name) : - PluginClient(name) { - - FILELog::ReportingLevel() = FILELog::FromString("INFO"); - AddMessageFilter < tsm3Message > (this, &MobilityOperationPlugin::HandleMobilityOperationMessage); - SubscribeToMessages(); - -} - -MobilityOperationPlugin::~MobilityOperationPlugin() { -} - -void MobilityOperationPlugin::UpdateConfigSettings() { - -} - -void MobilityOperationPlugin::OnConfigChanged(const char *key, const char *value) { - PluginClient::OnConfigChanged(key, value); - UpdateConfigSettings(); -} - - -void MobilityOperationPlugin::HandleMobilityOperationMessage(tsm3Message &msg, routeable_message &routeableMsg ) { - auto mobilityOperation = msg.get_j2735_data(); - // FILE_LOG(logDEBUG) << "Checking log level : " << FILELog::ReportingLevel(); - PLOG(logDEBUG) << "Received MobilityOperation message (encoded) : " << routeableMsg.get_payload_str(); - PLOG(logDEBUG) << "Header Host BSM ID : " << mobilityOperation->header.hostBSMId.buf; - PLOG(logDEBUG) << "Header Host Static ID : " << mobilityOperation->header.hostStaticId.buf; - PLOG(logDEBUG) << "Header Plan ID : " << mobilityOperation->header.planId.buf; - PLOG(logDEBUG) << "Header Target Static ID : " << mobilityOperation->header.targetStaticId.buf; - PLOG(logDEBUG) << "Header Timestamp : " << mobilityOperation->header.timestamp.buf; - PLOG(logDEBUG) << "Body OperationParams : " << mobilityOperation->body.operationParams.buf; - PLOG(logDEBUG) << "Body Strategy : " << mobilityOperation->body.strategy.buf; - - -} - -void MobilityOperationPlugin::OnStateChange(IvpPluginState state) { - PluginClient::OnStateChange(state); - - if (state == IvpPluginState_registered) { - UpdateConfigSettings(); - } -} - - -int MobilityOperationPlugin::Main() { - FILE_LOG(logINFO) << "Starting plugin."; - - uint64_t lastSendTime = 0; - - while (_plugin->state != IvpPluginState_error) { - - - - usleep(100000); //sleep for microseconds set from config. - } - - return (EXIT_SUCCESS); -} -} - -int main(int argc, char *argv[]) { - return run_plugin < MobilityOperationPlugin::MobilityOperationPlugin > ("MobilityOperationPlugin", argc, argv); -} - diff --git a/src/v2i-hub/MobilityOperationPlugin/src/MobilityOperationPlugin.h b/src/v2i-hub/MobilityOperationPlugin/src/MobilityOperationPlugin.h deleted file mode 100644 index 6d704e3b0..000000000 --- a/src/v2i-hub/MobilityOperationPlugin/src/MobilityOperationPlugin.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef SRC_MOBILITYOPERATIONPLUGIN_H_ -#define SRC_MOBILITYOPERATIONPLUGIN_H_ -#include "PluginClient.h" -#include - - -using namespace std; -using namespace tmx; -using namespace tmx::utils; -using namespace tmx::messages; - -namespace MobilityOperationPlugin { - -class MobilityOperationPlugin: public PluginClient { -public: - MobilityOperationPlugin(std::string); - virtual ~MobilityOperationPlugin(); - int Main(); -protected: - - void UpdateConfigSettings(); - - // Virtual method overrides. - void OnConfigChanged(const char *key, const char *value); - - void OnStateChange(IvpPluginState state); - - void HandleMobilityOperationMessage(tsm3Message &msg, routeable_message &routeableMsg); - -private: -}; -} -#endif \ No newline at end of file diff --git a/src/v2i-hub/PortDrayagePlugin/CMakeLists.txt b/src/v2i-hub/PortDrayagePlugin/CMakeLists.txt new file mode 100644 index 000000000..8a8883b35 --- /dev/null +++ b/src/v2i-hub/PortDrayagePlugin/CMakeLists.txt @@ -0,0 +1,24 @@ +PROJECT ( PortDrayagePlugin VERSION 5.0 LANGUAGES CXX ) + +SET (TMX_PLUGIN_NAME "PortDrayage") +set(CMAKE_AUTOMOC ON) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wno-unused-variable") + +find_package(Qt5Core REQUIRED) +find_package(Qt5Network REQUIRED) + + +include_directories( "/usr/local/include/pdclient") + + + +message(CMAKE MODULE : ${CMAKE_MODULE_PATH} ) + + +BuildTmxPlugin ( ) + +target_link_libraries(${PROJECT_NAME} PRIVATE pdclient ) +target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Network ssl crypto ) +target_link_libraries(${PROJECT_NAME} PUBLIC tmxutils) + diff --git a/src/v2i-hub/PortDrayagePlugin/manifest.json b/src/v2i-hub/PortDrayagePlugin/manifest.json new file mode 100644 index 000000000..a3ee8f40c --- /dev/null +++ b/src/v2i-hub/PortDrayagePlugin/manifest.json @@ -0,0 +1,78 @@ +{ + "name":"PortDrayagePlugin", + "description":"PortDrayagePlugin for sending freight trucks automated actions in a port.", + "version":"@PROJECT_VERSION@", + "exeLocation":"/bin/PortDrayagePlugin", + "coreIpAddr":"127.0.0.1", + "corePort":24601, + "messageTypes":[ + { + "type":"J2735", + "subtype":"TMSG03-P", + "description":"MobilityOperation message is a prototyping message with a configurable payload." + } + ], + "configuration":[ + { + "key":"Database_IP", + "default":"127.0.0.1", + "description":"IP address of database" + }, + { + "key":"Database_Port", + "default":"3306", + "description":"Port of database" + }, + { + "key":"Database_Username", + "default":"root", + "description":"Username for database" + }, + { + "key":"Database_Password", + "default":"ivp", + "description":"Password for database" + }, + { + "key":"Database_Name", + "default":"PORT_DRAYAGE", + "description":"Name of database." + }, + { + "key":"LogLevel", + "default":"INFO", + "description":"The log level for this plugin" + }, + { + "key":"Webservice_Host", + "default":"127.0.0.1", + "description":"PortDrayage Webservice Host Address" + }, + { + "key":"Webservice_Port", + "default": "8090", + "description": "PortDrayage WebService Port" + }, + { + "key":"Webservice_Secure", + "default": "false", + "description": "Boolean flag set to true for HTTPS communication" + }, + { + "key":"Webservice_Polling_Frequency", + "default": "5", + "description": "Polling Frequency for PortDrayage Webservice action status in seconds" + }, + { + "key":"Holding_Lat", + "default":"45.45", + "description":"Latitude Coordinate for Holding Area GPS Location in Degrees(-90,90)." + }, + { + "key":"Holding_Lon", + "default":"-45.45", + "description":"Longitude Coordinate for Holding Area GPS Location in Degrees(-180,180)." + } + + ] +} diff --git a/src/v2i-hub/PortDrayagePlugin/src/PortDrayagePlugin.cpp b/src/v2i-hub/PortDrayagePlugin/src/PortDrayagePlugin.cpp new file mode 100644 index 000000000..da15930d0 --- /dev/null +++ b/src/v2i-hub/PortDrayagePlugin/src/PortDrayagePlugin.cpp @@ -0,0 +1,491 @@ +/** + * Copyright (C) 2019 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this 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. + */ +#include "PortDrayagePlugin.h" + + + +namespace PortDrayagePlugin { + +PortDrayagePlugin::PortDrayagePlugin(string name) : + PluginClient(name) { + // Plugin Handles MobilityOperation Messages + AddMessageFilter < tsm3Message > (this, &PortDrayagePlugin::HandleMobilityOperationMessage); + SubscribeToMessages(); + +} + +PortDrayagePlugin::~PortDrayagePlugin() { +} + +void PortDrayagePlugin::UpdateConfigSettings() { + + lock_guard lock(_cfgLock); + + std::string _database_username; + std::string _database_password; + uint16_t _database_port; + std::string _database_ip; + std::string _database_name; + // Database configuration + GetConfigValue("Database_Username", _database_username); + GetConfigValue("Database_Password", _database_password); + GetConfigValue("Database_IP",_database_ip); + GetConfigValue("Database_Port",_database_port); + GetConfigValue("Database_Name", _database_name); + // Port Drayage Web Service Configuration + uint16_t polling_frequency; + uint16_t polling_timeout; + std::string host; + uint16_t port; + bool secure; + // Host address + GetConfigValue("Webservice_Host", host); + // Host Port + GetConfigValue("Webservice_Port", port); + // True for HTTPS + GetConfigValue("Webservice_Secure", secure); + // Polling Frequency in seconds + GetConfigValue("Webservice_Polling_Frequency", polling_frequency); + + client = std::make_shared( host, port, secure, polling_frequency ); + // Port Holding Area Configurable location + GetConfigValue("Holding_Lat", _holding_lat); + GetConfigValue("Holding_Lon", _holding_lon); + PLOG(logDEBUG) << "Holding Area set : (" << _holding_lat << ", " << _holding_lon << ")" << std::endl; + + // Create DB connection + std::string connection_string = "tcp://" + _database_ip + ":" + std::to_string(_database_port); + try { + driver = get_driver_instance(); + con = driver->connect(connection_string,_database_username,_database_password); + con->setSchema(_database_name); + // Initialize PreparedStatements for MySQL + // Get next_action for given action_id + next_action_id = con->prepareStatement("SELECT next_action FROM freight WHERE action_id = ? "); + // Get current action for given action_id + current_action = con->prepareStatement("SELECT * FROM freight WHERE action_id = ? "); + // Get first action for vehicle + first_action = con->prepareStatement("SELECT * FROM first_action WHERE cmv_id = ? " ); + // Insert action into freight table + insert_action = con->prepareStatement("INSERT INTO freight VALUES(?,?,?,?,?, UUID(), ?)"); + // Get action_id of the previous action given action_id + get_action_id_for_previous_action = con->prepareStatement("SELECT action_id FROM freight WHERE next_action = ? and operation = ? "); + // Update next_action for an action with given action_id + update_current_action = con->prepareStatement("UPDATE freight SET next_action = ? WHERE action_id = ?"); + + } + catch ( const sql::SQLException &e ) { + PLOG(logERROR) << "Error occurred during MYSQL Connection " << std::endl << e.what() << std::endl + << "Error occurred in file " << __FILE__ << " on line " << __LINE__ << std::endl + << "Error code " << e.getErrorCode() << std::endl + << "Error status " << e.getSQLState() << std::endl; + } + +} + +void PortDrayagePlugin::OnConfigChanged(const char *key, const char *value) { + PluginClient::OnConfigChanged(key, value); + UpdateConfigSettings(); +} + + +void PortDrayagePlugin::HandleMobilityOperationMessage(tsm3Message &msg, routeable_message &routeableMsg ) { + + // Retrieve J2735 Message + auto mobilityOperation = msg.get_j2735_data(); + + // String Stream for strategy and operationParams + std::stringstream strat; + std::stringstream payload; + + // Create ptree object for json + ptree pr; + + // Create new PortDrayage_Object pointer + std::unique_ptr pd( new PortDrayage_Object()); + + // Read strategy and operationParams + strat << mobilityOperation->body.strategy.buf; + payload << mobilityOperation->body.operationParams.buf; + + // Compare strategy to PortDrayage strategy + std::string strategy = strat.str(); + if ( strategy.compare(PORT_DRAYAGE_STRATEGY) == 0 ){ + try { + PLOG(logINFO) << "Body OperationParams : " << mobilityOperation->body.operationParams.buf + << std::endl << "Body Strategy : " << mobilityOperation->body.strategy.buf; + // Convert JSON payload to PortDrayage_Object + read_json(payload, pr); + *pd = readPortDrayageJson( pr ); + } + catch( const ptree_error &e ) { + PLOG(logERROR) << "Error parsing Mobility Operation payload: " << e.what() << std::endl; + } + // Handle actions that require PortDrayage WebService Input + if ( pd->operation.compare(operation_to_string(Operation::PICKUP)) == 0 ) { + client->request_loading_action( pd->cmv_id, pd->cargo_id, pd->action_id ); + } + else if ( pd->operation.compare(operation_to_string(Operation::DROPOFF)) == 0) { + client->request_unloading_action( pd->cmv_id, pd->cargo_id, pd->action_id ); + } + else if ( pd->operation.compare(operation_to_string(Operation::CHECKPOINT)) == 0) { + // If holding == 1 insert HOLDING action into table + int holding = client->request_inspection( pd->cmv_id, pd->cargo_id, pd->action_id ); + if ( holding == 1 ) { + insert_holding_action_into_table( *pd ); + } + } + else if ( pd->operation.compare(operation_to_string(Operation::HOLDING)) == 0) { + string previous_checkpoint_id = retrieve_holding_inspection_action_id( pd->action_id ); + client->request_holding( previous_checkpoint_id ); + } + + + PLOG(logDEBUG) << "Port Drayage Message" << std::endl << + "cmv_id : " << pd->cmv_id << std::endl << + "cargo_id : " << pd->cargo_id << std::endl << + "cargo : " << pd->cargo << std::endl << + "operation : " << pd->operation << std::endl << + "location_lat : " << pd->location_lat << std::endl << + "location_long : " << pd->location_long << std::endl << + "destination_lat : " << pd->destination_lat << std::endl << + "destination_long : " << pd->destination_long << std::endl << + "action_id : " << pd->action_id << std::endl << + "next_action : " << pd->next_action << std::endl; + + + try{ + // Retrieve first or next action + PortDrayage_Object *new_action = new PortDrayage_Object(); + if ( pd->action_id.empty() ) { + PLOG(logDEBUG) << "Retrieving first action." << std::endl; + *new_action = retrieveFirstAction( pd->cmv_id ); + } + else { + PLOG(logDEBUG) << "Retrieving next action." << std::endl; + *new_action = retrieveNextAction( pd->action_id ); + } + + if ( !new_action->action_id.empty()) { + // Initializer vars + tsm3Message mob_msg; + tsm3EncodedMessage mobilityENC; + tmx::message_container_type container; + std::unique_ptr msg; + + // Create operationParams payload json + ptree payload = createPortDrayageJson( *new_action ); + + // Create XML MobilityOperationMessage + ptree message = createMobilityOperationXml( payload ); + std::stringstream content; + write_xml(content, message); + try { + // Uper encode message + container.load(content); + mob_msg.set_contents(container.get_storage().get_tree()); + mobilityENC.encode_j2735_message( mob_msg); + msg.reset(); + msg.reset(dynamic_cast(factory.NewMessage(api::MSGSUBTYPE_TESTMESSAGE03_STRING))); + string enc = mobilityENC.get_encoding(); + PLOG(logDEBUG) << "Encoded outgoing message : " << std::endl << mobilityENC.get_payload_str(); + msg->refresh_timestamp(); + msg->set_payload(mobilityENC.get_payload_str()); + msg->set_encoding(enc); + msg->set_flags(IvpMsgFlags_RouteDSRC); + msg->addDsrcMetadata(172,0xBFEE); + msg->refresh_timestamp(); + routeable_message *rMsg = dynamic_cast(msg.get()); + BroadcastMessage(*rMsg); + } + catch ( const J2735Exception &e) { + PLOG(logERROR) << "Error occurred during message encoding " << std::endl << e.what() << std::endl; + } + } + else { + PLOG(logWARNING) << "Could not find action!" << std::endl; + } + + } + catch ( const sql::SQLException &e ) { + PLOG(logERROR) << "Error occurred during MYSQL Connection " << std::endl << e.what() << std::endl + << "Error code " << e.getErrorCode() << std::endl + << "Error status " << e.getSQLState() << std::endl; + } + } +} + + +ptree PortDrayagePlugin::createPortDrayageJson( const PortDrayage_Object &pd_obj) { + ptree json_payload; + json_payload.put("cmv_id", pd_obj.cmv_id ); + json_payload.put("cargo_id", pd_obj.cargo_id ); + ptree destination; + destination.put("latitude", pd_obj.destination_lat); + destination.put("longitude", pd_obj.destination_long); + json_payload.put_child("destination",destination); + json_payload.put("operation", pd_obj.operation ); + json_payload.put("action_id", pd_obj.action_id ); + return json_payload; +} + + +ptree PortDrayagePlugin::createMobilityOperationXml( const ptree &json_payload ) { + ptree mobilityOperationXml; + std::stringstream pl; + write_json( pl, json_payload); + // Create XML MobilityOperationMessage + ptree message; + ptree header; + ptree body; + body.put("strategy",PORT_DRAYAGE_STRATEGY); + body.put("operationParams", pl.str()); + header.put("hostStaticId", "UNSET"); + header.put("targetStaticId", "UNSET"); + header.put("hostBSMId", "00000000"); + header.put("planId", "00000000-0000-0000-0000-000000000000"); + header.put("timestamp", "0000000000000000000"); + message.put_child("header", header); + message.put_child("body",body); + mobilityOperationXml.put_child( "TestMessage03", message); + return mobilityOperationXml; +} + + +PortDrayagePlugin::PortDrayage_Object PortDrayagePlugin::retrieveNextAction(const std::string &action_id ) { + std::unique_ptr rtn( new PortDrayage_Object()); + try{ + // Set action_id + next_action_id->setString(1,action_id); + // Get current action + sql::ResultSet *cur_action = next_action_id->executeQuery(); + if ( cur_action->first() ) { + std::string next = cur_action->getString("next_action"); + // Set action_id to next_action + current_action->setString(1,next); + // Retrieve next action + sql::ResultSet *cur_action = current_action->executeQuery(); + // Create PortDrayage_Object + if ( cur_action->first() ) { + rtn->cmv_id = cur_action->getString("cmv_id"); + rtn->operation = cur_action->getString("operation"); + rtn->action_id = cur_action->getString("action_id"); + rtn->cargo_id = cur_action->getString("cargo_id"); + rtn->destination_long = cur_action->getDouble("destination_long"); + rtn->destination_lat = cur_action->getDouble("destination_lat"); + rtn->next_action = cur_action->getString("next_action"); + + PLOG(logDEBUG) << "Port Drayage Message : " << std::endl << + "cmv_id : " << rtn->cmv_id << std::endl << + "cargo_id : " << rtn->cargo_id << std::endl << + "operation : " << rtn->operation << std::endl << + "destination_lat : " << rtn->destination_lat << std::endl << + "destination_long : " << rtn->destination_long << std::endl << + "action_id : " << rtn->action_id << std::endl << + "next_action : " << rtn->next_action << std::endl; + } + else { + // If we are able to retrieve the current action but not it's next_action we can + // assume it was the last action in the DB. + PLOG(logINFO) << "Last action completed! No action found with action id " << next << std::endl; + + } + } + } + catch ( const sql::SQLException &e ) { + PLOG(logERROR) << "Error occurred during MYSQL Connection " << std::endl << e.what() << std::endl + << "Error code " << e.getErrorCode() << std::endl + << "Error status " << e.getSQLState() << std::endl; + } + return *rtn; +} + +PortDrayagePlugin::PortDrayage_Object PortDrayagePlugin::retrieveFirstAction( const std::string &cmv_id ) { + std::unique_ptr rtn( new PortDrayage_Object()); + try{ + // Set cmv_id + first_action->setString(1,cmv_id); + // Retrieve first action of first_action table + sql::ResultSet *cur_action = first_action->executeQuery(); + if ( cur_action->first() ) { + // Create Port Drayage object + rtn->cmv_id = cur_action->getString("cmv_id"); + rtn->operation = cur_action->getString("operation"); + rtn->action_id = cur_action->getString("action_id"); + rtn->cargo_id = cur_action->getString("cargo_id"); + rtn->destination_long = cur_action->getDouble("destination_long"); + rtn->destination_lat = cur_action->getDouble("destination_lat"); + rtn->next_action =cur_action->getString("next_action"); + PLOG(logDEBUG) << "Port Drayage Message" << std::endl << + "cmv_id : " << rtn->cmv_id << std::endl << + "cargo_id : " << rtn->cargo_id << std::endl << + "operation : " << rtn->operation << std::endl << + "destination_lat : " << rtn->destination_lat << std::endl << + "destination_long : " << rtn->destination_long << std::endl << + "action_id : " << rtn->action_id << std::endl << + "next_action : " << rtn->next_action << std::endl; + return *rtn; + } + else { + PLOG(logERROR) << "No first action for cmv_id : " << cmv_id << " found!"; + return *rtn; + } + + + } + catch ( const sql::SQLException &e ) { + PLOG(logERROR) << "Error occurred during MYSQL Connection " << std::endl << e.what() << std::endl + << "Error code " << e.getErrorCode() << std::endl + << "Error status " << e.getSQLState() << std::endl; + return *rtn; + } + +} + + +PortDrayagePlugin::PortDrayage_Object PortDrayagePlugin::readPortDrayageJson( const ptree &pr ) { + std::unique_ptr pd( new PortDrayage_Object()); + try { + pd->cmv_id = pr.get_child("cmv_id").get_value(); + boost::optional child = pr.get_child_optional( "action_id" ); + if( !child ) + { + PLOG(logINFO) << "No action_id present! This is the vehicle's first action" << std::endl; + } + else { + pd->action_id = child.get_ptr()->get_value(); + // For eventually tracking of completed actions + pd->operation = pr.get_child("operation").get_value(); + child = pr.get_child_optional("cargo_id"); + if ( child ) { + pd->cargo_id = pr.get_child("cargo_id").get_value(); + } + child = pr.get_child_optional("location"); + if ( child ) { + ptree location = pr.get_child("location"); + pd->location_lat =location.get_child("latitude").get_value(); + pd->location_long = location.get_child("longitude").get_value(); + } + + + } + return *pd.get(); + + } + catch( const ptree_error &e ) { + PLOG(logERROR) << "Error parsing Mobility Operation payload: " << e.what() << std::endl; + return *pd.get(); + } +} + +void PortDrayagePlugin::insert_holding_action_into_table( const PortDrayage_Object ¤t_action ) { + std::unique_ptr next_action( new PortDrayage_Object()); + try{ + + *next_action = retrieveNextAction(current_action.action_id); + PLOG(logDEBUG1) << "Insert Holding action between " << current_action.action_id << " and " + << next_action->action_id << "." << std::endl; + //INSERT INTO FREIGHT VALUES(cmv_id,cargo_id,_holding_lat,_holding_lon,HOLDING, UUID(), next_action->action_id) + insert_action->setString(1,current_action.cmv_id); + insert_action->setString(2,current_action.cargo_id); + insert_action->setDouble(3,_holding_lat); + insert_action->setDouble(4,_holding_lon); + insert_action->setString(5, "HOLDING_AREA"); + insert_action->setString(6, next_action->action_id); + PLOG(logDEBUG) << "Query : INSERT INTO FREIGHT VALUES(" + << current_action.cmv_id << ", " << current_action.cargo_id << ", " + << _holding_lat << ", " << _holding_lon << ", UUID(), HOLDING_AREA )" << std::endl; + sql::ResultSet *res = insert_action->executeQuery(); + + // SELECT action_id FROM freight WHERE next_action = ? and operation = ? + get_action_id_for_previous_action->setString(1, next_action->action_id); + get_action_id_for_previous_action->setString(2, "HOLDING_AREA"); + PLOG(logDEBUG) << "Query : SELECT action_id FROM freight WHERE next_action = " + << next_action->action_id << " and operation = HOLDING_AREA " << std::endl; + + res = get_action_id_for_previous_action->executeQuery(); + res->first(); + if ( res->isFirst() ) { + PLOG(logDEBUG) << "Query Result: " << res->first() << std::endl; + } + std::string action_id = res->getString("action_id"); + + // UPDATE freight SET next_action = ? WHERE action_id = ? + update_current_action->setString( 1, action_id); + update_current_action->setString( 2, current_action.action_id); + PLOG(logDEBUG) << "Query : UPDATE freight SET next_action = " + << action_id << " WHERE action_id = " << current_action.action_id << std::endl; + res = update_current_action->executeQuery(); + } + catch ( sql::SQLException &e ) { + PLOG(logERROR) << "Error occurred during MYSQL Connection " << std::endl << e.what() << std::endl + << "Error code " << e.getErrorCode() << std::endl + << "Error status " << e.getSQLState() << std::endl; + } +} + +std::string PortDrayagePlugin::retrieve_holding_inspection_action_id( const std::string &action_id ) { + try{ + get_action_id_for_previous_action->setString(1, action_id); + get_action_id_for_previous_action->setString(2, "PORT_CHECKPOINT"); + PLOG(logDEBUG) << "Query : SELECT action_id FROM freight WHERE next_action = " + << action_id << " and operation = PORT_CHECKPOINT " << std::endl; + + sql::ResultSet *res = get_action_id_for_previous_action->executeQuery(); + res->first(); + if ( res->isFirst() ) { + PLOG(logDEBUG) << "Query Result: " << res->first() << std::endl; + } + std::string action_id = res->getString("action_id"); + return action_id; + } + catch ( sql::SQLException &e ) { + PLOG(logERROR) << "Error occurred during MYSQL Connection " << std::endl << e.what() << std::endl + << "Error code " << e.getErrorCode() << std::endl + << "Error status " << e.getSQLState() << std::endl; + return ""; + } +} + +/** + * Trigger when Plugin state changes + * + * @param state IvpPluginState + */ +void PortDrayagePlugin::OnStateChange(IvpPluginState state) { + PluginClient::OnStateChange(state); + + if (state == IvpPluginState_registered) { + UpdateConfigSettings(); + } +} + + +int PortDrayagePlugin::Main() { + uint64_t lastSendTime = 0; + while (_plugin->state != IvpPluginState_error) { + usleep(100000); //sleep for microseconds set from config. + } + return (EXIT_SUCCESS); +} +} + +int main(int argc, char *argv[]) { + // Qt HttpClient setup + QCoreApplication a(argc, argv); + return run_plugin < PortDrayagePlugin::PortDrayagePlugin > ("PortDrayagePlugin", argc, argv); +} + diff --git a/src/v2i-hub/PortDrayagePlugin/src/PortDrayagePlugin.h b/src/v2i-hub/PortDrayagePlugin/src/PortDrayagePlugin.h new file mode 100644 index 000000000..c823ac3b3 --- /dev/null +++ b/src/v2i-hub/PortDrayagePlugin/src/PortDrayagePlugin.h @@ -0,0 +1,223 @@ +/** + * Copyright (C) 2019 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this 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. + */ +#ifndef SRC_PortDrayagePlugin_H_ +#define SRC_PortDrayagePlugin_H_ +#include "PluginClient.h" +#include +#include +#include +#include +#include "mysql_connection.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "WebServiceClient.h" + +using namespace std; +using namespace tmx; +using namespace tmx::utils; +using namespace tmx::messages; +using namespace boost::property_tree; +using namespace OpenAPI; + +namespace PortDrayagePlugin { +// constant for MobilityOperation strategy +static CONSTEXPR const char *PORT_DRAYAGE_STRATEGY = "carma/port_drayage"; + +// Enumeration for different operations +enum Operation { + PICKUP,DROPOFF,CHECKPOINT,HOLDING,ENTER_STAGING,EXIT_STAGING,ENTER_PORT,EXIT_PORT +}; + +std::string operation_to_string( Operation operation ) { + switch(operation) { + case PICKUP: + return "PICKUP"; + case DROPOFF: + return "DROPOFF"; + case CHECKPOINT: + return "PORT_CHECKPOINT"; + case HOLDING: + return "HOLDING_AREA"; + case ENTER_STAGING: + return "ENTER_STAGING_AREA"; + case EXIT_STAGING: + return "EXIT_STAGING_AREA"; + case ENTER_PORT: + return "ENTER_PORT"; + case EXIT_PORT: + return "EXIT_PORT"; + default: + return "INVALID_OPERATION"; + } +} +/** + * PortDrayagePlugin is a V2X-Hub plugin for automating Freight truck interactions for + * moving containers between and Port and a Staging Area. The plugin process MobilityOperation + * messages with the strategy PORT_DRAYAGE_STRATEGY. The payload of this MobilityOperation + * message is a JSON object consisting of mainly : + * action_id : unique identifier for the action + * vehicle_id : unique static identifier for the vehicle (NOT BSMID) + * operation : string enumeration describing the action that is to take place + * This Plugin requires a MySQL database with two table to store all vehicle action (table name: freight) and + * to store the first action for any given vehicle (table name : first_action). Upon initial communication + * with V2X-Hub the vehicle will just send an ENTER_STAGING_AREA actions with no action ID. When this initial + * message is received by V2X-Hub it will query the first_action table for the vehicle first action. Every action + * in the database is linked to a next action. Once the vehicle completes an action it notifies V2X-Hub of completion + * by sending out the action it just completed. V2X-Hub will then query the database for the next linked action + * + * @author Paul Bourelly + * @version 6.2 + */ +class PortDrayagePlugin: public PluginClient { +public: + struct PortDrayage_Object { + std::string cmv_id; + std::string cargo_id; + bool cargo; + std::string operation; + double location_lat; + double location_long; + double destination_lat; + double destination_long; + std::string action_id; + std::string next_action; + }; + /** + * Construct a new MobililtyOperationPlugin with the given name. + * + * @param name The name to give the plugin for identification purposes + */ + PortDrayagePlugin(std::string); + /** + * Constructor without paramaters + */ + virtual ~PortDrayagePlugin(); + int Main(); +protected: + /** + * Update Configuration + */ + void UpdateConfigSettings(); + + // Virtual method overrides. + /** + * Method triggers UpdateConfigSettings() on configuration changes + */ + void OnConfigChanged(const char *key, const char *value); + + void OnStateChange(IvpPluginState state); + /** + * Method to create port drayage payload JSON ptree using a PortDrayage_Object. + * + * @param pd_obj Port Drayage object. + * @return json ptree + */ + ptree createPortDrayageJson( const PortDrayage_Object &pd_obj); + /** + * Method to create MobilityOperation XML ptree. + * + * @param ptree json payload + * @return MobilityOperation message XML ptree + */ + ptree createMobilityOperationXml( const ptree &json_payload); + + /** + * Handle MobilityOperation message. + * + * @param tsm3Message J2735 MobilityOperation message + * @param routeableMsg JSON MobilityOperation message + */ + void HandleMobilityOperationMessage(tsm3Message &msg, routeable_message &routeableMsg); + /** + * Retrieve next action from freight table using action_id + * + * @param action_id string + */ + PortDrayage_Object retrieveNextAction( const std::string &action_id ); + /** + * Retrieve first action from first_action table using cmv_id. + * + * @param cmv_id + * @return PortDrayage_Object of first action + */ + PortDrayage_Object retrieveFirstAction( const std::string &cmv_id ); + + /** + * Create PortDrayage_Object from ptree JSON. + * + * @param pr PortDrayage JSON + * @return PortDrayage_Object + */ + PortDrayage_Object readPortDrayageJson( const ptree &pr ); + + /** + * Dynamically inserts HOLDING_AREA action into mysql table between + * current_action and next_action. Current action should be PORT_CHECKPOINT + * and next_action should be EXIT_PORT + * + * @param current_action PORT_CHECKPOINT action + */ + void insert_holding_action_into_table(const PortDrayage_Object ¤t_action ); + + /** + * Retrieves HOLDING_AREA action when provided with PORT_CHECKPOINT action + * from mysql freight table. + * + * @return action_id of HOLDING_AREA action + */ + std::string retrieve_holding_inspection_action_id( const std::string &action_id ); + + +private: + // Database configuration values + + + + sql::Driver *driver; + sql::Connection *con; + + // Prepared Statements + sql::PreparedStatement *next_action_id; + sql::PreparedStatement *current_action; + sql::PreparedStatement *first_action; + sql::PreparedStatement *insert_action; + sql::PreparedStatement *get_action_id_for_previous_action; + sql::PreparedStatement *update_current_action; + + // Message Factory for J2735 messages + J2735MessageFactory factory; + + // Web Service Client + std::shared_ptr client; + + // Port HOLDING_AREA Configuration + double _holding_lat; + double _holding_lon; + +}; +std::mutex _cfgLock; + +} +#endif \ No newline at end of file diff --git a/src/v2i-hub/PortDrayagePlugin/src/WebServiceClient.cpp b/src/v2i-hub/PortDrayagePlugin/src/WebServiceClient.cpp new file mode 100644 index 000000000..9227946ac --- /dev/null +++ b/src/v2i-hub/PortDrayagePlugin/src/WebServiceClient.cpp @@ -0,0 +1,284 @@ +/** + * Copyright (C) 2019 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this 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. + */ +#include "WebServiceClient.h" + + +WebServiceClient::WebServiceClient() { + initialize(DEF_HOST, DEF_PORT, DEF_SECURITY, DEF_POLLING_FREQ); +} + +WebServiceClient::WebServiceClient(const std::string &host, uint16_t port, bool secure , uint16_t polling_frequency ) { + initialize(host, port, secure, polling_frequency); +} +void WebServiceClient::initialize(const std::string &host, uint16_t port, bool secure , uint16_t polling_frequency) { + this->polling_frequency = polling_frequency; + + // Create URL + std::unique_ptr url( new QUrl()); + url.get()->setHost(QString::fromStdString(host)); + url.get()->setPort(port); + if ( secure ) { + url.get()->setScheme(QString::fromStdString("https")); + } + else { + url.get()->setScheme(QString::fromStdString("http")); + + } + PLOG(logINFO) << "Setting API URL as " << url.get()->toString().toStdString() << std::endl; + // Initialize API + api = std::make_shared(0); + // Setup server config + api.get()->setNewServerForAllOperations( + *url.get(), + QString::fromStdString("V2X-Hub Configured PortDrayage WebService"), + QMap() + ); + +} + +void WebServiceClient::request_loading_action(const std::string &vehicle_id, const std::string &container_id, const std::string &action_id) { + std::unique_ptr req(new OAIContainerRequest ()); + std::unique_ptr loop( new QEventLoop()); + + // Disconnect duplicate signals + disconnect(api.get(), &OAIDefaultApi::loadingPostSignal, nullptr, nullptr); + disconnect(api.get(), &OAIDefaultApi::loadingPostSignalE, nullptr, nullptr); + + // Call back for POST /loading/ + connect(api.get(), &OAIDefaultApi::loadingPostSignal, this, [&]() { + PLOG(logINFO) << "Success /loading POST"; + loop->quit(); + }); + // Error call back for POST /loading/ + connect(api.get(), &OAIDefaultApi::loadingPostSignalE, this, [&](QNetworkReply::NetworkError error_code, QString error_str) { + PLOG(logERROR) << "Failure /loading POST : " << error_str.toStdString() << std::endl << "Error Code" << error_code; + loop->exit(1); + }); + + // Setup request + req->setVehicleId( QString::fromStdString( vehicle_id ) ) ; + req->setContainerId( QString::fromStdString( container_id ) ); + req->setActionId( QString::fromStdString( action_id ) ); + + PLOG(logINFO) << "Sending loading request : " << req->asJson().toStdString(); + api->loadingPost( *req.get() ); + loop->exec(); + // Poll loading action until complete + pollLoadingAction( req->getActionId() ); + + +} + +void WebServiceClient::request_unloading_action(const std::string &vehicle_id, const std::string &container_id, const std::string &action_id) { + std::unique_ptr req(new OAIContainerRequest ()); + std::unique_ptr loop( new QEventLoop()); + + // Disconnect duplicate signals + disconnect(api.get(), &OAIDefaultApi::unloadingPostSignal, nullptr, nullptr); + disconnect(api.get(), &OAIDefaultApi::unloadingPostSignalE, nullptr, nullptr); + + // Call back for POST /unloading/ + connect(api.get(), &OAIDefaultApi::unloadingPostSignal, this, [&]() { + PLOG(logINFO) << "Success /unloading POST"; + loop->quit(); + }); + // Error call back for POST /unloading/ + connect(api.get(), &OAIDefaultApi::unloadingPostSignalE, this, [&](QNetworkReply::NetworkError error_code, QString error_str) { + PLOG(logERROR) << "Failure /unloading POST : " << error_str.toStdString() << std::endl << "Error Code : " << error_code; + loop->exit(1); + }); + + // Setup request + req->setVehicleId( QString::fromStdString( vehicle_id ) ) ; + req->setContainerId( QString::fromStdString( container_id ) ); + req->setActionId( QString::fromStdString( action_id ) ); + + PLOG(logINFO) << "Sending unloading request : " << req->asJson().toStdString(); + api->unloadingPost( *req.get() ); + loop->exec(); + + // Polling unloading action until complete + pollUnloadingAction( req->getActionId() ); + +} + +int WebServiceClient::request_inspection(const std::string &vehicle_id, const std::string &container_id, const std::string &action_id ) { + std::unique_ptr req(new OAIInspectionRequest()); + std::unique_ptr loop( new QEventLoop()); + + // Disconnect all duplicate signals + disconnect(api.get(),&OAIDefaultApi::inspectionPostSignal, nullptr, nullptr ); + disconnect(api.get(),&OAIDefaultApi::inspectionPostSignalE, nullptr, nullptr ); + + // Call back for POST /inspection/ + connect(api.get(), &OAIDefaultApi::inspectionPostSignal, this, [&]() { + PLOG(logINFO) << "Success /inspection POST"; + loop->quit(); + }); + // Error call back for POST /inspection/ + connect(api.get(), &OAIDefaultApi::inspectionPostSignalE, this, [&](QNetworkReply::NetworkError error_code, QString error_str) { + PLOG(logERROR) << "Failure /inspection POST : " << error_str.toStdString() << std::endl << "Error Code :" << error_code; + loop->exit(1); + }); + + // Setup request + req->setVehicleId( QString::fromStdString( vehicle_id ) ) ; + req->setContainerId( QString::fromStdString( container_id ) ); + req->setActionId( QString::fromStdString( action_id ) ); + + PLOG(logINFO) << "Sending inspection request : " << req->asJson().toStdString(); + api->inspectionPost( *req.get() ); + loop->exec(); + + // Poll inspection status until complete or proceed to holding + return pollInspectionAction( req->getActionId() ); +} + +void WebServiceClient::request_holding( const std::string &action_id ) { + std::unique_ptr loop( new QEventLoop()); + + // Disconnect all duplicate signals + disconnect(api.get(), &OAIDefaultApi::inspectionHoldingActionIdPostSignal, nullptr, nullptr); + disconnect(api.get(), &OAIDefaultApi::inspectionHoldingActionIdPostSignalE, nullptr, nullptr); + + // Call back for POST /inspection/ + connect(api.get(), &OAIDefaultApi::inspectionHoldingActionIdPostSignal, [&]() { + PLOG(logINFO) << "Success /inspection/holding/{action_id} POST"; + loop->quit(); + }); + // Error call back for POST /inspection/ + connect(api.get(), &OAIDefaultApi::inspectionHoldingActionIdPostSignalE, [&](QNetworkReply::NetworkError error_code, QString error_str) { + PLOG(logERROR) << "Failure /inspection/holding/{action_id} POST : " << error_str.toStdString()<< std::endl << "Error Code : " << error_code; + loop->exit(1); + }); + PLOG(logINFO) << "Sending holding request for action_id : " << action_id << std::endl; + api.get()->inspectionHoldingActionIdPost( QString::fromStdString(action_id) ); + loop->exec(); + // Poll inspection action until complete + pollInspectionAction( QString::fromStdString( action_id ) ); + +} + +void WebServiceClient::pollLoadingAction( QString action_id ) { + PLOG(logDEBUG) << "Starting loading action Polling"; + std::unique_ptr loop( new QEventLoop()); + bool badResponse = true; + // Disconnect all duplicate signals + disconnect(api.get(), &OAIDefaultApi::loadingActionIdGetSignal, nullptr, nullptr); + disconnect(api.get(), &OAIDefaultApi::loadingActionIdGetSignalE, nullptr, nullptr); + + // Call back for Get /loading/{action_id} + connect(api.get(), &OAIDefaultApi::loadingActionIdGetSignal, this, [&](OAIContainerActionStatus loading_action) { + loading_status.reset( new OAIContainerActionStatus( loading_action.asJson( ) ) ); + PLOG(logINFO) << "Success /loading/{action_id} GET : " << loading_status->asJson().toStdString(); + badResponse = false; + loop->quit(); + }); + // Error call back for Get /loading/{action_id} + connect(api.get(), &OAIDefaultApi::loadingActionIdGetSignalE, this, + [&](OAIContainerActionStatus loading_action , QNetworkReply::NetworkError error_code, QString error_str) { + PLOG(logERROR) << "Failure loading/{action_id} GET :" << error_str.toStdString() << std::endl << "Error Code : " << error_code; + badResponse = true; + loop->exit(1); + }); + // Flag to continue polling until receiving a non error response from server + do { + api->loadingActionIdGet( action_id ); + loop->exec(); + // usleep coversion from seconds to microseconds + usleep( polling_frequency * 1e6 ); + } + while ( badResponse || loading_status->getStatus() != QString::fromStdString( "LOADED") ) ; + +} + +void WebServiceClient::pollUnloadingAction( QString action_id) { + PLOG(logDEBUG) << "Starting unloading action Polling"; + std::unique_ptr loop( new QEventLoop()); + + bool badResponse = true; + // Disconnect all duplicate signals + disconnect(api.get(), &OAIDefaultApi::unloadingActionIdGetSignal, nullptr, nullptr); + disconnect(api.get(), &OAIDefaultApi::unloadingActionIdGetSignalE, nullptr, nullptr); + // Call back for Get /unloading/{action_id} + connect(api.get(), &OAIDefaultApi::unloadingActionIdGetSignal, this, [&](OAIContainerActionStatus unloading_action) { + unloading_status.reset( new OAIContainerActionStatus( unloading_action.asJson() ) ); + PLOG(logINFO) << "Success /unloading/{action_id} GET : " << unloading_status->asJson().toStdString(); + badResponse = false; + loop->quit(); + }); + // Error call back for Get /unloading/{action_id} + connect(api.get(), &OAIDefaultApi::unloadingActionIdGetSignalE, this, + [&](OAIContainerActionStatus unloading_action , QNetworkReply::NetworkError error_code, QString error_str) { + PLOG(logERROR) << "Failure unloading/{action_id} GET :" << error_str.toStdString() << std::endl << "Error Code : " << error_code; + badResponse = true; + loop->exit(1); + }); + // Flag to continue polling until receiving a non error response from server + do { + api->unloadingActionIdGet( action_id ); + loop->exec(); + // usleep coversion from seconds to microseconds + usleep( polling_frequency * 1e6 ); + + } + while( badResponse || unloading_status->getStatus() != QString::fromStdString( "UNLOADED") ); +} + +int WebServiceClient::pollInspectionAction( QString action_id ) { + PLOG(logDEBUG) << "Starting inspection action Polling"; + std::unique_ptr loop( new QEventLoop()); + bool badResponse = true; + + // Disconnect all duplicate signals + disconnect(api.get(), &OAIDefaultApi::inspectionActionIdGetSignal, nullptr, nullptr); + disconnect(api.get(), &OAIDefaultApi::inspectionActionIdGetSignalE, nullptr, nullptr); + + // Call back for GET /inspection/{action_id} + connect(api.get(), &OAIDefaultApi::inspectionActionIdGetSignal, this , [&](OAIInspectionStatus inspection) { + inspection_status.reset( new OAIInspectionStatus( inspection.asJson() ) ); + PLOG(logINFO) << "Success /inspection/{action_id} GET : " << inspection_status->asJson().toStdString() << std::endl; + badResponse = false; + loop->quit(); + }); + // Error call back for /inspection/{action_id} + connect(api.get(), &OAIDefaultApi::inspectionActionIdGetSignalE, this, + [&](OAIInspectionStatus inspection , QNetworkReply::NetworkError error_code, QString error_str) { + PLOG(logERROR) << "Failure /inspection/{action_id} GET : " << error_str.toStdString() << std::endl << "Error Code : " << error_code; + badResponse = true; + loop->exit(1); + }); + do { + api->inspectionActionIdGet( action_id ); + loop->exec(); + + if (inspection_status->getStatus() == QString::fromStdString( "PASSED")){ + return 0; + } + else if (inspection_status->getStatus() == QString::fromStdString( "PROCEED_TO_HOLDING")) { + return 1; + } + // usleep coversion from seconds to microseconds + usleep( polling_frequency * 1e6 ); + + + } + while( badResponse || (inspection_status->getStatus() != QString::fromStdString( "PASSED") && + inspection_status->getStatus() != QString::fromStdString( "PROCEED_TO_HOLDING")) ); + return -1; +} + + diff --git a/src/v2i-hub/PortDrayagePlugin/src/WebServiceClient.h b/src/v2i-hub/PortDrayagePlugin/src/WebServiceClient.h new file mode 100644 index 000000000..f0f835259 --- /dev/null +++ b/src/v2i-hub/PortDrayagePlugin/src/WebServiceClient.h @@ -0,0 +1,144 @@ +/** + * Copyright (C) 2019 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this 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. + */ + +#pragma once +#include +#include +#include "PluginLog.h" +#include +#include +#include +#include + +using namespace OpenAPI; +using namespace tmx::utils; + +// Default values for no arg constructor +static CONSTEXPR const char *DEF_HOST = "127.0.0.1"; +static CONSTEXPR const uint16_t DEF_PORT = 8090; +static CONSTEXPR const uint16_t DEF_POLLING_FREQ = 5; +static CONSTEXPR const bool DEF_SECURITY = false; + +/** + * WebService REST Client using OpenAPI codegen library pdclient found under V2X-Hub/ext/pdclient. Contains several method to + * send POST requests for loading, unloading, and inspection actions and poll the action status. + * + * @author Paul Bourelly + */ +class WebServiceClient : public QObject +{ + Q_OBJECT +public slots: + +private: + // Stored in Seconds + uint16_t polling_frequency; + + + // OAIDefaultApi pointer + std::shared_ptr api; + std::shared_ptr loading_status; + std::shared_ptr unloading_status; + std::shared_ptr inspection_status; + /** + * Method to poll the status of a loading action with a given action id. + * + * @param action_id of the loading action to be polled + */ + void pollLoadingAction(QString action_id); + + /** + * Method to poll the status of a unloading action with a given action id. + * + * @param action_id of the unloading action to be polled + */ + void pollUnloadingAction(QString action_id); + + /** + * Method to poll the status of a inspection with a given action id. + * + * @param action_id of the inspection to be polled + * @return 0 if inspection is passed and 1 if further inspection at the holding area is requested + */ + int pollInspectionAction(QString action_id); + + /** + * Method to initialize server configuration and polling frequency + * + * @param host string host name of server + * @param port uint16_t port of server + * @param secure bool flag set to true for using HTTPS + * @param polling_frequency + */ + void initialize(const std::string &host, uint16_t port, bool secure , uint16_t polling_frequency); + + +public: + + /** + * Constructor without parameters + */ + WebServiceClient(); + + /** + * Constructor for WebServiceClient + * + * @param host string webservice host URL + * @param port uint8_t webservice port + * @param secure boolean flag set to true when using HTTPS + * @param int polling frequency in seconds for action status + * + */ + WebServiceClient(const std::string &host, uint16_t port, bool secure , uint16_t polling_frequency ); + + /** + * Method to request a loading action. Sends a HTTP POST call to the loading endpoint of the PortDrayage Webservice and then + * polls the status of the request every 5 seconds. Method will exit once loading action is completed. + * + * @param vehicle_id static unique identifier for vehicle + * @param container_id static unique identifier for container + * @param action_id static unique identifier for action + */ + void request_loading_action(const std::string &vehicle_id, const std::string &container_id, const std::string &action_id); + /** + * Method to request an unloading action. Sends a HTTP POST call to the unloading endpoint of the PortDrayage Webservice and then + * polls the status of the request every 5 seconds. Method will exit once unloading action is completed. + * + * @param vehicle_id static unique identifier for the vehicle + * @param container_id static unique identifier for the container + * @param action_id static unique identifier for the action + */ + void request_unloading_action(const std::string &vehicle_id, const std::string &container_id, const std::string &action_id); + /** + * Method to request an inspection action. Sends a HTTP POST call to the inspection endpoint of the PortDrayage Webservice and then + * polls the status of the request every 5 seconds. Method will exit once inspection action is completed or operator indicates the + * vehicle requires further inspection at the Holding area + * + * @param vehicle_id static unique identifier for the vehicle + * @param container_id static unique identifier for container + * @param action_id static unique identifier for the action + */ + int request_inspection(const std::string &vehicle_id, const std::string &container_id, const std::string &action_id); + /** + * Method request further inspection at the Holding area. Sends a HTTP POST call to inspection holding endpoint of the PortDrayage Webservice + * and then poll the status of the request every 5 seconds. Method will exit once inspection action is completed. + * + * @param action_id static unique identifier for action + */ + void request_holding(const std::string &action_id); + + +}; diff --git a/tools/port-drayage-webservice/.dockerignore b/tools/port-drayage-webservice/.dockerignore new file mode 100644 index 000000000..b2be670ee --- /dev/null +++ b/tools/port-drayage-webservice/.dockerignore @@ -0,0 +1,9 @@ +src/ +target/classes/ +target/generated-soures/ +target/generated-test-sources/ +target/maven-archiver/ +target/site/ +target/surefire-reports/ +target/test-classes/ +target/jacoco.exec diff --git a/tools/port-drayage-webservice/Dockerfile b/tools/port-drayage-webservice/Dockerfile new file mode 100644 index 000000000..f10c360d8 --- /dev/null +++ b/tools/port-drayage-webservice/Dockerfile @@ -0,0 +1,5 @@ +FROM adoptopenjdk/openjdk11:alpine-jre +RUN mkdir ~/port-drayage-webservice/ +COPY ./target/port-drayage-webservice-0.0.1-SNAPSHOT.jar ~/port-drayage-webservice/ +WORKDIR ~/port-drayage-webservice/ +ENTRYPOINT ["java","-jar","port-drayage-webservice-0.0.1-SNAPSHOT.jar"] \ No newline at end of file diff --git a/tools/port-drayage-webservice/pom.xml b/tools/port-drayage-webservice/pom.xml new file mode 100644 index 000000000..e146696c0 --- /dev/null +++ b/tools/port-drayage-webservice/pom.xml @@ -0,0 +1,139 @@ + + + 4.0.0 + + com.leidos + port-drayage-webservice + 0.0.1-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 2.5.5 + + + + + org.springframework.boot + spring-boot-starter-web + + + io.springfox + springfox-boot-starter + 3.0.0 + + + org.openapitools + jackson-databind-nullable + 0.2.1 + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-validation + + + + org.springframework.boot + spring-boot-starter-actuator + + + + com.fasterxml.jackson.core + jackson-core + + + + org.webjars + bootstrap + 4.0.0-2 + + + org.webjars + webjars-locator + 0.30 + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + + + + + org.openapitools + openapi-generator-maven-plugin + 5.1.0 + + + + generate + + + + ${project.basedir}/src/main/resources/port-drayage-webservice.yml + + spring + spring-boot + com.baeldung.openapi.api + com.baeldung.openapi.model + + ApiUtil.java + + + true + true + + + + + + + + org.jacoco + jacoco-maven-plugin + + + + com/baeldung/openapi/** + + + + + + prepare-agent + + + + report + test + + report + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + \ No newline at end of file diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/Application.java b/tools/port-drayage-webservice/src/main/java/com/leidos/Application.java new file mode 100644 index 000000000..2b6d3f403 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/Application.java @@ -0,0 +1,25 @@ +package com.leidos; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * Main class for SpringBoot application. {@link EnableAutoConfiguration} annotation allow spring to scan all sub-directories for defined beans. + * + * @author Paul Bourelly + */ + +@EnableAutoConfiguration +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + + +} \ No newline at end of file diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/area/Area.java b/tools/port-drayage-webservice/src/main/java/com/leidos/area/Area.java new file mode 100644 index 000000000..f1b6f2ed9 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/area/Area.java @@ -0,0 +1,16 @@ +package com.leidos.area; + +public enum Area { + STAGING_AREA("STAGING_AREA"), + PORT_AREA("PORT_AREA"); + private String name; + + Area(String name){ + this.name =name; + } + + public String getName(){ + return name; + } + +} diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/area/AreaBean.java b/tools/port-drayage-webservice/src/main/java/com/leidos/area/AreaBean.java new file mode 100644 index 000000000..6fcb09511 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/area/AreaBean.java @@ -0,0 +1,28 @@ +package com.leidos.area; + +import org.springframework.stereotype.Component; + +@Component +public class AreaBean { + + private Area area; + + /** + * Empty Constructor. + */ + public AreaBean() { + + } + + public void stagingArea() { + area = Area.STAGING_AREA; + } + + public void portArea() { + area = Area.PORT_AREA; + } + + public Area getArea() { + return area; + } +} diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/configuration/WebApplicationConfiguration.java b/tools/port-drayage-webservice/src/main/java/com/leidos/configuration/WebApplicationConfiguration.java new file mode 100644 index 000000000..3b70bdc7e --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/configuration/WebApplicationConfiguration.java @@ -0,0 +1,27 @@ +package com.leidos.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableSwagger2 +public class WebApplicationConfiguration { + + /** + * Allow Cross Origin Resource Sharing (CORS) for all endpoints. + * @return + */ + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurer() { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**"); + } + }; + } +} diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/controller/InspectionController.java b/tools/port-drayage-webservice/src/main/java/com/leidos/controller/InspectionController.java new file mode 100644 index 000000000..df1694509 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/controller/InspectionController.java @@ -0,0 +1,123 @@ +package com.leidos.controller; + +import com.baeldung.openapi.api.InspectionApi; +import com.baeldung.openapi.model.InspectionRequest; +import com.baeldung.openapi.model.InspectionStatus; +import com.baeldung.openapi.model.InspectionStatusList; +import com.baeldung.openapi.model.InspectionStatus.StatusEnum; +import com.leidos.inspection.InspectionActions; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +/** + * {@link RestController} for all inspection/ REST endpoints. Implements + * {@link InspectionApi} generated by openapi-generator-maven-plugin (see + * pom.xml), which configures endpoint content type, response type and path. + * + * @author Paul Bourelly + */ +@RestController +public class InspectionController implements InspectionApi { + + private static Logger logger = LoggerFactory.getLogger(InspectionController.class); + + // Injected InspectionActions spring bean + @Autowired + private InspectionActions inspectionActions; + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity inspectionPendingGet() { + return ResponseEntity.ok(inspectionActions.getPendingInspections()); + + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity inspectionActionIdGet(String actionId) { + logger.debug(String.format("Received GET inspection/%s .", actionId)); + InspectionStatus status = inspectionActions.getInspectionStatus(actionId); + if (status != null) + return ResponseEntity.ok(status); + return new ResponseEntity(HttpStatus.BAD_REQUEST); + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity inspectionPost(InspectionRequest request) { + logger.debug(String.format("Received POST inspection/ with payload : %s .", request)); + // Assure there is not current inspection with action_id + if (inspectionActions.getInspectionStatus(request.getActionId()) == null) { + inspectionActions.requestInspectionAction(request); + return new ResponseEntity<>(HttpStatus.CREATED); + } else { + logger.warn(String.format("Action with action ID %s already exists! Discarding potential duplicate request", + request.getActionId())); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity inspectionHoldingActionIdPost(String actionId) { + logger.debug(String.format("Received POST inspection/holding/%s .", actionId)); + InspectionStatus cur = inspectionActions.getCurrentInspection(); + // Check that action is current action and that status is PROCEED_TO_HOLDING + if (cur != null && cur.getActionId().equals(actionId) + && cur.getStatus().equals(StatusEnum.PROCEED_TO_HOLDING)) { + inspectionActions.requestHolding(); + return new ResponseEntity<>(HttpStatus.CREATED); + } else { + logger.warn(String.format( + "Action ID %s is not current inspection %s or does not have a status of PROCEED_TO_HOLDING AREA.\n Discarding potential duplicate request.", + actionId, inspectionActions.getCurrentInspection().toString())); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity inspectionCompleteActionIdPost(String actionId) { + logger.debug(String.format("Received POST inspection/complete/%s .", actionId)); + InspectionStatus cur = inspectionActions.getCurrentInspection(); + if (cur != null && cur.getActionId().equals(actionId)) { + inspectionActions.completeInspection(); + return new ResponseEntity<>(HttpStatus.CREATED); + } else { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity inspectionHoldActionIdPost(String actionId) { + logger.debug(String.format("Received POST inspection/hold/%s .", actionId)); + InspectionStatus cur = inspectionActions.getCurrentInspection(); + if (cur != null && cur.getActionId().equals(actionId)) { + inspectionActions.proceedToHolding(); + return new ResponseEntity<>(HttpStatus.CREATED); + } else { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + } + +} diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/controller/LoadingController.java b/tools/port-drayage-webservice/src/main/java/com/leidos/controller/LoadingController.java new file mode 100644 index 000000000..f0f92230a --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/controller/LoadingController.java @@ -0,0 +1,105 @@ +package com.leidos.controller; + +import com.baeldung.openapi.api.LoadingApi; +import com.baeldung.openapi.model.ActionStatusList; +import com.baeldung.openapi.model.ContainerActionStatus; +import com.baeldung.openapi.model.ContainerRequest; +import com.leidos.loading.LoadingActions; + +import org.springframework.web.bind.annotation.RestController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +/** + * {@link RestController} for all /loading REST API endpoints. Implements + * {@link LoadingApi} interface generated by openapi codegen to define methods + * of endpoint responses. + * + * @author Paul Bourelly + */ +@RestController +public class LoadingController implements LoadingApi { + + private static Logger logger = LoggerFactory.getLogger(LoadingController.class); + + /** + * Injected {@link LoadingActions} Spring Bean + */ + @Autowired + private LoadingActions loadingActions; + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity loadingPendingGet() { + return ResponseEntity.ok(loadingActions.getPendingActions()); + + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity loadingActionIdGet(String actionId) { + logger.debug(String.format("Received GET loading/%s .", actionId)); + ContainerActionStatus action = loadingActions.getContainerActionStatus(actionId); + if (action != null) + return ResponseEntity.ok(action); + return new ResponseEntity(HttpStatus.BAD_REQUEST); + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity loadingPost(ContainerRequest request) { + logger.debug(String.format("Received POST loading/ with payload : %s .", request)); + // Check no action already exists for given action ID + if (loadingActions.getContainerActionStatus(request.getActionId()) == null) { + loadingActions.requestLoadingAction(request); + return new ResponseEntity<>(HttpStatus.CREATED); + } else { + logger.warn(String.format("Action with action ID %s already exists! Discarding potential duplicate request", + request.getActionId())); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity loadingStartActionIdPost(String actionId) { + logger.debug(String.format("Received POST loading/start/%s .", actionId)); + ContainerActionStatus cur = loadingActions.getCurrentAction(); + if (cur != null && cur.getActionId().equals(actionId)) { + loadingActions.startCurrentAction(); + return new ResponseEntity<>(HttpStatus.CREATED); + } else { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity loadingCompleteActionIdPost(String actionId) { + logger.debug(String.format("Received POST loading/complete/%s .", actionId)); + ContainerActionStatus cur = loadingActions.getCurrentAction(); + if (cur != null && cur.getActionId().equals(actionId)) { + loadingActions.completeCurrentAction(); + return new ResponseEntity<>(HttpStatus.CREATED); + } else { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + } + +} diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/controller/UIActionController.java b/tools/port-drayage-webservice/src/main/java/com/leidos/controller/UIActionController.java new file mode 100644 index 000000000..708ad8695 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/controller/UIActionController.java @@ -0,0 +1,77 @@ +package com.leidos.controller; + +import com.baeldung.openapi.api.UiactionApi; +import com.leidos.area.Area; +import com.leidos.area.AreaBean; +import com.leidos.inspection.InspectionActions; +import com.leidos.loading.LoadingActions; +import com.leidos.unloading.UnloadingActions; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +public class UIActionController implements UiactionApi { + + private static Logger logger = LoggerFactory.getLogger(UIActionController.class); + + /** + * Injected {@link LoadingActions} Spring Bean + */ + @Autowired + private LoadingActions loadingActions; + + /** + * Injected {@link UnloadingActions} Spring Bean + */ + @Autowired + private UnloadingActions unloadingActions; + + /** + * Injected {@link InspectionActions} Spring Bean + */ + @Autowired + private InspectionActions inspectionActions; + + /** + * + */ + @Autowired + private AreaBean areaBean; + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity uiactionResetPost() { + inspectionActions.clear(); + unloadingActions.clear(); + loadingActions.clear(); + logger.warn("Web Service Actions were cleared!"); + return new ResponseEntity(HttpStatus.OK); + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity uiactionAreaAreaPost(String area) { + if ( area.equals(Area.STAGING_AREA.getName())) { + areaBean.stagingArea(); + return new ResponseEntity<>(HttpStatus.CREATED); + } + else if ( area.equals(Area.PORT_AREA.getName())) { + areaBean.portArea(); + return new ResponseEntity<>(HttpStatus.CREATED); + } + else { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + +} diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/controller/UnloadingController.java b/tools/port-drayage-webservice/src/main/java/com/leidos/controller/UnloadingController.java new file mode 100644 index 000000000..2559a67c1 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/controller/UnloadingController.java @@ -0,0 +1,104 @@ +package com.leidos.controller; + +import com.baeldung.openapi.api.UnloadingApi; +import com.baeldung.openapi.model.ActionStatusList; +import com.baeldung.openapi.model.ContainerActionStatus; +import com.baeldung.openapi.model.ContainerRequest; +import com.leidos.unloading.UnloadingActions; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +/** + * {@link RestController} for all /unloading REST API endpoints. Implements + * {@link Unloading} interface generated by openapi codegen to define methods of + * endpoint responses. + * + * @author Paul Bourelly + */ +@RestController +public class UnloadingController implements UnloadingApi { + + Logger logger = LoggerFactory.getLogger(UnloadingController.class); + + /** + * Injected {@link UnloadingActions} Spring Bean + */ + @Autowired + UnloadingActions unloadingActions; + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity unloadingPendingGet() { + return ResponseEntity.ok(unloadingActions.getPendingActions()); + + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity unloadingActionIdGet(String actionId) { + logger.debug(String.format("Received GET unloading/%s .", actionId)); + ContainerActionStatus action = unloadingActions.getContainerActionStatus(actionId); + if (action != null) + return ResponseEntity.ok(action); + return new ResponseEntity(HttpStatus.BAD_REQUEST); + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity unloadingPost(ContainerRequest request) { + logger.debug(String.format("Received POST unloading/ with payload : %s .", request)); + // Check no action already exists for given action ID + if (unloadingActions.getContainerActionStatus(request.getActionId()) == null) { + unloadingActions.requestUnloadingAction(request); + return new ResponseEntity<>(HttpStatus.CREATED); + } else { + logger.warn(String.format("Action with action ID %s already exists! Discarding potential duplicate request", + request.getActionId())); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity unloadingStartActionIdPost(String actionId) { + logger.debug(String.format("Received POST unloading/start/%s .", actionId)); + ContainerActionStatus cur = unloadingActions.getCurrentAction(); + if (cur != null && cur.getActionId().equals(actionId)) { + unloadingActions.startCurrentAction(); + return new ResponseEntity<>(HttpStatus.CREATED); + } else { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + } + + /** + * {@inheritDoc} + */ + @Override + public ResponseEntity unloadingCompleteActionIdPost(String actionId) { + logger.debug(String.format("Received POST unloading/complete/%s .", actionId)); + ContainerActionStatus cur = unloadingActions.getCurrentAction(); + if (cur != null && cur.getActionId().equals(actionId)) { + unloadingActions.completeCurrentAction(); + return new ResponseEntity<>(HttpStatus.CREATED); + } else { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + } +} diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/controller/UserInterfaceController.java b/tools/port-drayage-webservice/src/main/java/com/leidos/controller/UserInterfaceController.java new file mode 100644 index 000000000..cf276d3a6 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/controller/UserInterfaceController.java @@ -0,0 +1,54 @@ +package com.leidos.controller; + + +import com.leidos.area.Area; +import com.leidos.area.AreaBean; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class UserInterfaceController { + + @Autowired + public AreaBean areaBean; + + + @GetMapping("/") + public String main( Model model) { + if ( areaBean.getArea() != null ) + return "index"; + else { + return "landing"; + } + } + + @GetMapping("/loading") + public String loading() { + return "_loading"; + + } + @GetMapping("/unloading") + public String unloading() { + return "_unloading"; + + } + @GetMapping("/inspection") + public String inspection() { + return "_inspection"; + + } + + /** + * Keeping access to landing page under this URL for testing purposes. + * @return + */ + @GetMapping("/debug/landing") + public String main() { + return "landing"; + + } + +} diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/inspection/InspectionActions.java b/tools/port-drayage-webservice/src/main/java/com/leidos/inspection/InspectionActions.java new file mode 100644 index 000000000..b3c8c2896 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/inspection/InspectionActions.java @@ -0,0 +1,221 @@ +package com.leidos.inspection; + +import com.baeldung.openapi.api.InspectionApi; +import com.baeldung.openapi.model.InspectionRequest; +import com.baeldung.openapi.model.InspectionStatus; +import com.baeldung.openapi.model.InspectionStatus.StatusEnum; +import com.baeldung.openapi.model.InspectionStatusList; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * {@link InspectionActions} is a spring bean for managing inspections. Only + * allows for a single inspection to be in progress at a time and is stored as + * the {@link InspectionActions#currentInspection}. Any inspections requested + * while the current inspection is not yet completed will be added to + * {@link InspectionActions#pendingInspections} list. This list is then used to + * populate the current action after an action is completed. Each completed + * action is stored in the {@link InspectionActions#completedInspections} list. + * + * @author Paul Bourelly + */ +@Component +public class InspectionActions { + + private static Logger logger = LoggerFactory.getLogger(InspectionActions.class); + + // List of pending inspection statuses + private InspectionStatusList pendingInspections = new InspectionStatusList(); + + // List of completed inspections + private InspectionStatusList completedInspections = new InspectionStatusList(); + + // Current in progress action + private InspectionStatus currentInspection; + + /** + * Empty Constructor + */ + public InspectionActions() { + } + + /** + * Getter for pending inspection. + * + * @return {@link InspectionStatusList} list of pending inspection. + */ + public InspectionStatusList getPendingInspections() { + return pendingInspections; + } + + /** + * Getter for completed inspections. + * + * @return {@link InspectionStatusList} list of completed inspection. + */ + public InspectionStatusList getCompletedInspections() { + return completedInspections; + } + + /** + * Getter for current action. + * + * @return {@link InspectionStatus} current action. + */ + public InspectionStatus getCurrentInspection() { + return currentInspection; + } + + /** + * Create {@link InspectionStatus} for valid {@link InspectionRequest}s. Valid + * requests require vehicleId and containerId. Set as current inspection if none + * already exists or added to list of pending inspections if current inspection + * is still in progress. + * + * @param request {@link InspectionRequest} Request to load container. + */ + public void requestInspectionAction(InspectionRequest request) { + if (request != null) { + InspectionStatus inspectionStatus = new InspectionStatus(); + inspectionStatus.setContainerId(request.getContainerId()); + inspectionStatus.setVehicleId(request.getVehicleId()); + inspectionStatus.setActionId(request.getActionId()); + inspectionStatus.setStatus(StatusEnum.PENDING); + inspectionStatus.setRequested(System.currentTimeMillis()); + + // If no current action set as current action + if (currentInspection == null) { + currentInspection = inspectionStatus; + } + + // else add to list of pending action + else { + pendingInspections.addInspectionsItem(inspectionStatus); + } + } else { + logger.warn("Attempted to add null InspectionRequest!"); + } + + } + + /** + * Searches all inspections ( pending, current and completed ) for a given + * actionId and returns {@link InspectionStatus}. Returns null if non is found. + * + * @param actionId unique string to identify action + * @return {@link InspectionStatus} for given action. Null if no action is found + * or null action id is provided. + */ + public InspectionStatus getInspectionStatus(String actionId) { + if (actionId != null) { + // Pending actions ( null check since arraylist is initially null ) + if (pendingInspections.getInspections() != null) { + for (InspectionStatus inspectionStatus : pendingInspections.getInspections()) { + if (actionId.equals(inspectionStatus.getActionId())) { + return inspectionStatus; + } + } + } + // Current action + if (currentInspection != null && actionId.equals(currentInspection.getActionId())) { + return currentInspection; + } + // Completed actions ( null check since arraylist is initially null ) + if (completedInspections.getInspections() != null) { + for (InspectionStatus inspectionStatus : completedInspections.getInspections()) { + if (actionId.equals(inspectionStatus.getActionId())) { + return inspectionStatus; + } + } + } + logger.warn(String.format("No inspection action with action ID %s !", actionId)); + return null; + } + logger.warn("Null action id is not valid!"); + return null; + } + + /** + * To complete inspection set {@link InspectionActions#currentInspection} status + * to {@link StatusEnum#PASSED}. Current inspection is then added to the + * completed inspections list and the first pending action , if any are present + * is set as the new current action. If no pending actions are present the + * current action is set to null. + * + */ + public void completeInspection() { + if (currentInspection != null) { + // Set current inspection to PASSED + currentInspection.setStatus(StatusEnum.PASSED); + currentInspection.setCompleted(System.currentTimeMillis()); + completedInspections.addInspectionsItem(currentInspection); + // If there are any pending actions set them to current + if (pendingInspections.getInspections() != null && !pendingInspections.getInspections().isEmpty()) { + currentInspection = pendingInspections.getInspections().remove(0); + } + // else set current to null + else { + currentInspection = null; + } + + } else + logger.warn("No current inspection in progress!"); + } + + /** + * To indicate that the vehicle under inspection is required to proceed to the + * holding area for further inspection an operator will use this request to set + * {@link InspectionActions#currentInspection} status to. + * {@link StatusEnum#PROCEED_TO_HOLDING}. + */ + public void proceedToHolding() { + if (currentInspection != null) { + currentInspection.setStatus(StatusEnum.PROCEED_TO_HOLDING); + } else + logger.warn("No current inspection in progress!"); + } + + /** + * Vehicle under current inspection, which has been instructed to proceed to + * holding area by operator will indicate it has arrived at the holding area and + * is prepared for further inspection with this request which sets the status of + * the {@link InspectionActions#currentInspection} to + * {@link StatusEnum#HOLDING}. + */ + public void requestHolding() { + if (currentInspection != null) { + currentInspection.setStatus(StatusEnum.HOLDING); + } else + logger.warn("No current inspection in progress!"); + } + + /** + * Clear all inspection actions + */ + public void clear() { + if ( pendingInspections.getInspections() != null ) + pendingInspections.getInspections().clear(); + if ( completedInspections.getInspections() != null ) + completedInspections.getInspections().clear(); + currentInspection = null; + } + + /** + * Method to return the number of waiting actions for UI tab notification + */ + public int waitingActions() { + if ( pendingInspections.getInspections() != null && !pendingInspections.getInspections().isEmpty()) { + // plus one for current action + return pendingInspections.getInspections().size() + 1; + } + else if ( currentInspection != null ) { + return 1; + } + else { + return 0; + } + } + +} diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/loading/LoadingActions.java b/tools/port-drayage-webservice/src/main/java/com/leidos/loading/LoadingActions.java new file mode 100644 index 000000000..fce9f187c --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/loading/LoadingActions.java @@ -0,0 +1,201 @@ +package com.leidos.loading; + +import com.baeldung.openapi.model.ActionStatusList; +import com.baeldung.openapi.model.ContainerActionStatus; +import com.baeldung.openapi.model.ContainerRequest; +import com.baeldung.openapi.model.ContainerActionStatus.StatusEnum; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * {@link LoadingActions} is a spring bean for managing loading actions. Only + * allows for a single loading action to be in progress at a time and is stored + * as the {@link LoadingActions#currentAction}. Any loading actions requested + * while the current action is not yet completed will be added to + * {@link LoadingActions#pendingActions} list. This list is then used to + * populate the current action after an action is completed. Each completed + * action is stored in the {@link LoadingActions#completedActions} list. + * + * @author Paul Bourelly + */ +@Component +public class LoadingActions { + + private static Logger logger = LoggerFactory.getLogger(LoadingActions.class); + + // List of all pending loading actions + private ActionStatusList pendingActions = new ActionStatusList(); + + // List of completed loading actions + private ActionStatusList completedActions = new ActionStatusList(); + + // Current Loading Action + private ContainerActionStatus currentAction; + + /** + * Empty Constructor. + */ + public LoadingActions() { + + } + + /** + * Getter for pending loading actions. + * + * @return {@link ActionStatusList} list of pending loading actions + */ + public ActionStatusList getPendingActions() { + return pendingActions; + } + + /** + * Getter for completed Actions. + * + * @return {@link ActionStatusList} list of completed actions + */ + public ActionStatusList getCompletedActions() { + return completedActions; + } + + /** + * Getter for current Action. + * + * @return {@link ContainerActionStatus} current in progress loading + */ + public ContainerActionStatus getCurrentAction() { + return currentAction; + } + + /** + * Create {@link ContainerActionStatus} for valid {@link ContainerRequest}s. + * Valid requests require vehicleId and containerId. Valid request will be set + * as {@link LoadingActions#currentAction} if no current action is present or + * added to list of pending actions. + * + * @param request {@link ContainerRequest} Request to load container. + */ + public void requestLoadingAction(ContainerRequest request) { + if (request != null) { + ContainerActionStatus requestedAction = new ContainerActionStatus(); + requestedAction.setContainerId(request.getContainerId()); + requestedAction.setVehicleId(request.getVehicleId()); + requestedAction.setActionId(request.getActionId()); + requestedAction.setStatus(ContainerActionStatus.StatusEnum.PENDING); + requestedAction.setRequested(System.currentTimeMillis()); + // Add action to list of pending actions if an + // action is already in progress. Otherwise set + // as current action + if (currentAction != null) + pendingActions.addActionsItem(requestedAction); + else + currentAction = requestedAction; + } else { + logger.warn("Attempted to add null ContainerRequest!"); + } + + } + + /** + * Searches all loading actions ( pending, current and completed ) for a given + * actionId and returns {@link ContainerActionStatus}. Returns null if non is found. + * + * @param actionId unique string to identify action + * @return {@link InspectionStatus} for given action. Null if no action is found + * or null action id is provided. + */ + public ContainerActionStatus getContainerActionStatus(String actionId) { + if (actionId != null) { + // First search pending loading actions ( null check since actions array is null + // before adding values ) + if (pendingActions.getActions() != null) { + for (ContainerActionStatus containerAction : pendingActions.getActions()) { + if (actionId.equals(containerAction.getActionId())) { + return containerAction; + } + } + } + // search current action + if (currentAction != null && actionId.equals(currentAction.getActionId())) { + return currentAction; + } + // Search completed loading actions ( null check since actions array is null + // before adding values ) + if (completedActions.getActions() != null) { + for (ContainerActionStatus containerAction : completedActions.getActions()) { + if (actionId.equals(containerAction.getActionId())) { + return containerAction; + } + } + } + logger.warn(String.format("No loading actions exist with action ID %s !", actionId)); + return null; + } + logger.warn("Null action id is not valid!"); + return null; + } + + /** + * Mark {@link LoadingActions#currentAction} as in progress by setting the + * {@link ContainerActionStatus#status} to {@link StatusEnum#LOADING}. + */ + public void startCurrentAction() { + if (currentAction != null) { + logger.debug(String.format("Starting loading for action %s", currentAction.toString())); + currentAction.setStatus(StatusEnum.LOADING); + } else + logger.warn("There is no current action!"); + } + + /** + * Mark {@link LoadingActions#currentAction} as complete and move it to the + * completedActions list. If there are pending actions, set the next pending + * action to current action, else set current action to null. + */ + public void completeCurrentAction() { + if (currentAction != null) { + currentAction.setStatus(ContainerActionStatus.StatusEnum.LOADED); + currentAction.setCompleted(System.currentTimeMillis()); + logger.debug(String.format("Complete loading for action %s", currentAction.toString())); + logger.debug(String.format("Complete loading for action %s", currentAction.toString())); + completedActions.addActionsItem(currentAction); + // Remove first item in list of pending actions and set it to current action + if (pendingActions.getActions() != null && !pendingActions.getActions().isEmpty()) { + currentAction = pendingActions.getActions().remove(0); + } else { + currentAction = null; + } + } else + logger.warn("There is no current action!"); + + } + + /** + * Clear all loading actions + */ + public void clear() { + if ( pendingActions.getActions() != null ) + pendingActions.getActions().clear(); + if ( completedActions.getActions() != null ) + completedActions.getActions().clear(); + currentAction = null; + } + + /** + * Method to return the number of waiting actions for UI tab notification + */ + public int waitingActions() { + if ( pendingActions.getActions() != null && !pendingActions.getActions().isEmpty() ) { + // plus one for current action + return pendingActions.getActions().size() + 1; + } + else if ( currentAction != null ) { + return 1; + } + else { + return 0; + } + } + +} diff --git a/tools/port-drayage-webservice/src/main/java/com/leidos/unloading/UnloadingActions.java b/tools/port-drayage-webservice/src/main/java/com/leidos/unloading/UnloadingActions.java new file mode 100644 index 000000000..23255a828 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/java/com/leidos/unloading/UnloadingActions.java @@ -0,0 +1,196 @@ +package com.leidos.unloading; + +import com.baeldung.openapi.model.ActionStatusList; +import com.baeldung.openapi.model.ContainerActionStatus; +import com.baeldung.openapi.model.ContainerRequest; +import com.baeldung.openapi.model.ContainerActionStatus.StatusEnum; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * {@link UnloadingActions} is a spring bean for managing unloading actions. + * Only allows for a single unloading action to be in progress at a time and is + * stored as the {@link UnloadingActions#currentAction}. Any unloading actions + * requested while the current action is not yet completed will be added to + * {@link UnloadingActions#pendingActions} list. This list is then used to + * populate the current action after an action is completed. Each completed + * action is stored in the {@link UnloadingActions#completedActions} list. + * + * @author Paul Bourelly + */ +@Component +public class UnloadingActions { + + private static Logger logger = LoggerFactory.getLogger(UnloadingActions.class); + // List of all pending unloading actions + private ActionStatusList pendingActions = new ActionStatusList(); + + // List of completed unloading actions + private ActionStatusList completedActions = new ActionStatusList(); + + // Current unloading Action + private ContainerActionStatus currentAction; + + /** + * Empty Constructor + */ + public UnloadingActions() { + } + + /** + * Getter for pending unloading actions + * + * @return {@link ActionStatusList} list of pending unloading actions + */ + public ActionStatusList getPendingActions() { + return pendingActions; + } + + /** + * Getter for completed Actions + * + * @return {@link ActionStatusList} list of completed actions + */ + public ActionStatusList getCompletedActions() { + return completedActions; + } + + /** + * Getter for current Action + * + * @return {@link ContainerActionStatus} current in progress unloading + */ + public ContainerActionStatus getCurrentAction() { + return currentAction; + } + + /** + * Create {@link ContainerActionStatus} for valid {@link ContainerRequest}s. + * Valid requests require vehicleId and containerId. Valid request will be set + * as {@link UnloadingActions#currentAction} if no current action is present or + * added list of pending actions. + * + * @param request {@link ContainerRequest} Request to load container on to a + * vehicle + */ + public void requestUnloadingAction(ContainerRequest request) { + if (request != null) { + ContainerActionStatus requestedAction = new ContainerActionStatus(); + requestedAction.setContainerId(request.getContainerId()); + requestedAction.setVehicleId(request.getVehicleId()); + requestedAction.setActionId(request.getActionId()); + requestedAction.setStatus(ContainerActionStatus.StatusEnum.PENDING); + requestedAction.setRequested(System.currentTimeMillis()); + // Add action to list of pending actions if an + // action is already in progress. Otherwise set + // as current action + if (currentAction != null) + pendingActions.addActionsItem(requestedAction); + else + currentAction = requestedAction; + } else { + logger.warn("Attempted to add null ContainerRequest!"); + } + + } + + /** + * Searches all unloading actions ( pending, current and completed ) for a given + * actionId and returns {@link ContainerActionStatus}. Returns null if non is found. + * + * @param actionId unique string to identify action + * @return {@link InspectionStatus} for given action. Null if no action is found + * or null action id is provided. + */ + public ContainerActionStatus getContainerActionStatus(String actionId) { + if (actionId != null) { + // First search pending loading actions ( null check since actions array is null + // before adding values ) + if (pendingActions.getActions() != null) { + for (ContainerActionStatus containerAction : pendingActions.getActions()) { + if (actionId.equals(containerAction.getActionId())) { + return containerAction; + } + } + } + // search current action + if (currentAction != null && actionId.equals(currentAction.getActionId())) { + return currentAction; + } + // Search completed loading actions ( null check since actions array is null + // before adding values ) + if (completedActions.getActions() != null) { + for (ContainerActionStatus containerAction : completedActions.getActions()) { + if (actionId.equals(containerAction.getActionId())) { + return containerAction; + } + } + } + logger.warn(String.format("No unloading actions exist with action ID %s !", actionId)); + return null; + } + logger.warn("Null action id is not valid!"); + return null; + } + + /** + * Mark {@link UnloadingActions#currentAction} as in progress by setting the + * {@link ContainerActionStatus#status} to {@link StatusEnum#UNLOADING}. + */ + public void startCurrentAction() { + if (currentAction != null) { + currentAction.setStatus(StatusEnum.UNLOADING); + } else + logger.warn("There is no current action!"); + } + + /** + * Mark {@link UnloadingActions#currentAction} as complete and move it to the + * completedActions list. If there are pending actions, set the next pending + * action to current action, else set current action to null. + */ + public void completeCurrentAction() { + if (currentAction != null) { + currentAction.setStatus(StatusEnum.UNLOADED); + currentAction.setCompleted(System.currentTimeMillis()); + completedActions.addActionsItem(currentAction); + // Remove first item in list of pending actions and set it to current action + if (pendingActions.getActions() != null && !pendingActions.getActions().isEmpty()) { + currentAction = pendingActions.getActions().remove(0); + } else { + currentAction = null; + } + } else + logger.warn("There is no current action!"); + + } + + /** + * Clear all unloading actions + */ + public void clear() { + if ( pendingActions.getActions() != null ) + pendingActions.getActions().clear(); + if ( completedActions.getActions() != null ) + completedActions.getActions().clear(); + currentAction = null; + } + + /** + * Method to return the number of waiting actions for UI tab notification + */ + public int waitingActions() { + if ( pendingActions.getActions() != null && !pendingActions.getActions().isEmpty() ) { + // plus one for current action + return pendingActions.getActions().size() + 1; + } + else if ( currentAction != null ) { + return 1; + } + else { + return 0; + } + } +} diff --git a/tools/port-drayage-webservice/src/main/resources/application.properties b/tools/port-drayage-webservice/src/main/resources/application.properties new file mode 100644 index 000000000..d01b3f16d --- /dev/null +++ b/tools/port-drayage-webservice/src/main/resources/application.properties @@ -0,0 +1,30 @@ +# +# Keystore properties for SSL HTTPS hosting. Requires a java key store which can be generated using JDK with the following command : +# keytool -genkey -keyalg RSA -alias tutorial -keystore tutorial.jks -storepass password -validity 365 -keysize 4096 -storetype pkcs12 + +# server.ssl.key-store=src/main/resources/tutorial.jks +# server.ssl.key-store-type=pkcs12 +# server.ssl.key-store-password=password +# server.ssl.key-password=password +# server.ssl.key-alias=tutorial + +# Set UI and REST API server port +server.port=8090 + +# Spring boot actuator properties allow for rest endpoint exposure for monitoring spring bean status for debuging. Should be disable for production +# Documentation: https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html +management.endpoints.web.exposure.include=* + + +# Logging configuration + +# Set output log file +#logging.file=log/application.log + +# Set class/package level log level +#logging.level.com.leidos.loading.LoadingActions=DEBUG + +# Set root log level +#logging.level.root=INFO + + diff --git a/tools/port-drayage-webservice/src/main/resources/port-drayage-webservice.yml b/tools/port-drayage-webservice/src/main/resources/port-drayage-webservice.yml new file mode 100755 index 000000000..403b87d28 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/resources/port-drayage-webservice.yml @@ -0,0 +1,444 @@ +openapi: 3.0.0 +info: + title: Port Drayage Web Service. + description: Web Service for Loading/Unloading/Inspection interactions for Port Drayage Operations. + version: "1.0" +servers: + - url: http://127.0.0.1:8090 + description: Unsecured hosting for development + - url: https://127.0.0.1:8443 + description: Secured hosting for deployment +paths: + /uiaction/reset: + post: + summary: Clear Web Service Actions + description: + Request will clear all actions in InspectionActions, LoadingActions, and UnloadingActions. + responses: + "201": + description: Created + /uiaction/area/{area}: + post: + parameters: + - in: path + name: area + schema: + type: string + required: true + description: Area Enumeration indicating where web service is deployed. + summary: Select Area Of Operations. + description: Indicates where the web service is deployed. Possible valid area of operations include PORT_AREA and STAGING_AREA + responses: + "201": + description: Created + "400": + description: Invalid Request + + /loading: + post: + summary: Request a container is loaded on to freight vehicle. + description: + Provide ContainerRequest JSON to request a container with a given id be loaded on a vehicle with a given id.\ + Also requires an action id to uniquely identify the requested action. If an action already exists for a given action id\ + request will be discarded as duplicate and result in 400 response. + requestBody: + description: Request contains container ID, Vehicle ID and an Action ID + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/ContainerRequest" + responses: + "201": + description: Created + "400": + description: Bad Request + /loading/pending: + get: + summary: List of all pending loading actions. + description: + Provides a list of ContainerActionStatus JSON objects describing the loading actions waiting to be started.\ + Any action requested while there is a current action in progress will be added to this list. Actions in this list will\ + replace the current action after it is completed in a first-in first-out order. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ActionStatusList" + /loading/start/{action_id}: + post: + parameters: + - in: path + name: action_id + schema: + type: string + required: true + description: ID of action + summary: Start a loading action. + description: + Will attempt to start current loading action. This REST endpoint is only intended for UI form submission. Will\ + be triggered on UI interaction to indicate a loading action has started. Will return 400 if provided action id is not \ + current action. + responses: + "201": + description: Created + "400": + description: Bad Request + /loading/complete/{action_id}: + post: + parameters: + - in: path + name: action_id + schema: + type: string + required: true + description: ID of action + summary: Complete a loading action. + description: + Will attempt to complete current loading action. This REST endpoint is only intended for UI form submission. Will\ + be triggered on UI interaction to indicate a loading action has been completed. Will return 400 if provided action id is not\ + current action. + responses: + "201": + description: Created + "400": + description: Bad Request + /loading/{action_id}: + get: + parameters: + - in: path + name: action_id + schema: + type: string + required: true + description: ID of action + summary: Returns action with given ID + description: Returns action with given ID. If none is found returns 400. Intended for polling the status of a request action. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ContainerActionStatus" + "400": + description: Bad Request + /unloading: + post: + summary: Request a container is unloaded on to freight Vehicle. + description: + Provide ContainerRequest JSON to request a container with a given id be unloaded on a vehicle with a given id.\ + Also requires an action id to uniquely identify the requested action. If an action already exists for a given action id\ + request will be discarded as duplicate and result in 400 response. + requestBody: + description: Request contains container ID, Vehicle ID and an Action ID + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/ContainerRequest" + responses: + "201": + description: Created + /unloading/pending: + get: + summary: List of all pending unloading actions and status. + description: + Provides a list of ContainerActionStatus JSON describing the unloading actions waiting to be started.\ + Any action requested while there is a current action in progress will be added to this list. Actions in this list will\ + replace the current action after it is completed in a first-in first-out order. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ActionStatusList" + /unloading/start/{action_id}: + post: + parameters: + - in: path + name: action_id + schema: + type: string + required: true + description: ID of action + summary: Start an unloading action. + description: + Will attempt to start current unloading action. This REST endpoint is only intended for UI form submission. Will\ + be triggered on UI interaction to indicate a unloading action has started. Will return 400 if provided action id is not current\ + action. + responses: + "201": + description: Created + "400": + description: Bad Request + /unloading/complete/{action_id}: + post: + parameters: + - in: path + name: action_id + schema: + type: string + required: true + description: ID of action + summary: Complete an unloading action. + description: + Will attempt to complete current unloading action. This REST endpoint is only intended for UI form submission. Will\ + be triggered on UI interaction to indicate an unloading action has been completed. Will return 400 if provided action id is not\ + current action. + responses: + "201": + description: Created + "400": + description: Bad Request + /unloading/{action_id}: + get: + parameters: + - in: path + name: action_id + schema: + type: string + required: true + description: ID of action + summary: Returns action with given ID + description: Returns action with given ID. If none is found returns 400. Intended for polling the status of a request action. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ContainerActionStatus" + "400": + description: Bad Request + /inspection: + post: + summary: Request a container is inspected on to Freight Vehicle. + description: + Provide InspectionRequest JSON to request a container with a given id be inspected on a vehicle with a given id.\ + Also requires an action id to uniquely identify the requested action. If an action already exists for a given action id\ + request will be discarded as duplicate and result in 400 response. + requestBody: + description: Request contains container ID and Vehicle ID + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/InspectionRequest" + responses: + "201": + description: Created + "400": + description: Bad Request + /inspection/holding/{action_id}: + post: + parameters: + - in: path + name: action_id + schema: + type: string + required: true + description: ID of action + summary: Vehicle has arrive at Holding area an is waiting on inspection. + description: + After being instructed to proceed to holding area and navigating to holding area, vehicle will request further inspection at holding\ + area. This request will be sent from the PortDrayage V2X-Hub Plugin after receiving a vehicles arrival message at the holding area.\ + Will return 400 if not current action or status is not PROCEED_TO_HOLDING and discard request. + responses: + "201": + description: Created + "400": + description: Bad Request + /inspection/pending: + get: + summary: List of all pending inspection actions and status. + description: + Provides a list of InspectionStatus JSON objects describing the inspection actions waiting to be started.\ + Any action requested while there is a current action in progress will be added to this list. Actions in this list will\ + replace the current action after it is completed in a first-in first-out order. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/InspectionStatusList" + /inspection/complete/{action_id}: + post: + parameters: + - in: path + name: action_id + schema: + type: string + required: true + description: ID of action + summary: Complete an inspection action. + description: + Will attempt to complete current inspection. This REST endpoint is only intended for UI form submission. Will\ + be triggered on UI interaction to indicate an inspection has been completed. Will return 400 if provided action id is not\ + current action. + responses: + "201": + description: Created + "400": + description: Bad Request + /inspection/hold/{action_id}: + post: + parameters: + - in: path + name: action_id + schema: + type: string + required: true + description: ID of action + summary: Request vehicle proceed to holding area for further inspection + description: Will attempt to request vehicle proceed to holding area for further inspection. Will return 400 if no current action + responses: + "201": + description: Created + "400": + description: Bad Request + /inspection/{action_id}: + get: + parameters: + - in: path + name: action_id + schema: + type: string + required: true + description: ID of action + summary: Returns action with given ID + description: Returns action with given ID. If non is found returns 400. Intended for polling inspection status. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/InspectionStatus" + "400": + description: Bad Request +components: + schemas: + ContainerRequest: + title: Container Request + type: object + properties: + vehicle_id: + type: string + description: ID of vehicle + container_id: + type: string + description: ID of container + action_id: + type: string + description: ID of action + required: + - vehicle_id + - container_id + - action_id + ContainerActionStatus: + title: Container Action Status + type: object + properties: + vehicle_id: + type: string + description: ID of vehicle + container_id: + type: string + description: ID of container + action_id: + type: string + description: ID of action + status: + type: string + enum: + - LOADING + - UNLOADING + - LOADED + - UNLOADED + - PENDING + - ABORTED + requested: + type: integer + format: int64 + completed: + type: integer + format: int64 + required: + - vehicle_id + - container_id + - action_id + - status + - requested + ActionStatusList: + title: List of Container Action Status elements + type: object + properties: + actions: + type: array + items: + type: object + $ref: "#/components/schemas/ContainerActionStatus" + InspectionRequest: + title: Inspection Request + type: object + properties: + vehicle_id: + type: string + description: ID of vehicle + container_id: + type: string + description: ID of container + action_id: + type: string + description: ID of action + required: + - vehicle_id + - container_id + - action_id + InspectionStatus: + title: Inspection Status + type: object + properties: + vehicle_id: + type: string + description: ID of vehicle + container_id: + type: string + description: ID of container + action_id: + type: string + description: ID of action + status: + type: string + enum: + - PENDING + - PROCEED_TO_HOLDING + - PASSED + - FAILED + - HOLDING + requested: + type: integer + format: int64 + completed: + type: integer + format: int64 + required: + - vehicle_id + - container_id + - action_id + - status + - requested + InspectionStatusList: + title: List of Container Action Status elements + type: object + properties: + inspections: + type: array + items: + type: object + $ref: "#/components/schemas/InspectionStatus" diff --git a/tools/port-drayage-webservice/src/main/resources/static/css/index.css b/tools/port-drayage-webservice/src/main/resources/static/css/index.css new file mode 100644 index 000000000..dba98161e --- /dev/null +++ b/tools/port-drayage-webservice/src/main/resources/static/css/index.css @@ -0,0 +1,99 @@ +/* Index Page Style Sheet */ + +/* Navigation bar holds tabs and CARMA-Streets logo*/ +.navigation-bar{ + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: space-between; +} +/*Overwrite bootstrap nav-tabs class stop tabs from wrapping when screen is resized*/ +.nav-tabs{ + display: flex; + flex-direction: row; + flex-wrap: nowrap; +} +.carma-streets-logo{ + width: auto; + max-height: 90px; +} +/* Align icons to bottom of tab */ +.icons{ + max-height:40px; + max-width: 60px; + align-self: flex-end; +} +/* Style individual tabs */ +.tabs{ + display: flex; + clear: both; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + align-self: center; + width: 100%; + height: 100%; + /* overwrite some of the nav-link styling */ + border: 2px black solid !important; + border-bottom: none !important; + color: lightgray !important; +} +/* Overwrite active tab styling for green backgrould */ +.nav-link.active{ + /* Override bootstrap styling */ + background-color: hsla(120, 100%, 25%, 0.4) !important; + border: 2px black solid !important; + border-bottom: none !important; + color: black !important; + outline: none !important; + box-shadow: none !important; +} +/* Set tab label styling */ +.tab-label{ + align-self: flex-end; + margin-left: 7px; + margin-bottom: 0 !important; +} +/* Overwrite bootstrap badge style for notification badges for tabs */ +.badge { + height: fit-content; + color: black; +} + +/* Styling for Tab Content */ + +/* Add border to bootstrap tab content styling*/ +.tab-content{ + border: 2px black solid; + padding: 10px; +} +/* Overwrite bootstrap jumbotron styling for dialog popup */ +.jumbotron{ + display: flex; + flex-direction: row; + flex-wrap: nowrap; + padding: 1rem 1rem !important; +} +/* Left part of dialog popup*/ +.action-dialog-left{ + width: 60%; + height: 100%; +} +/* Right part of dialog popup*/ +.action-dialog-right{ + width: 40%; + color: darkblue; + border: 2px black dashed ; + border-radius: 5px; + display: flex; + justify-content: center; + align-items: center; + font-size: xxx-large; +} +/* Clear Actions button styling */ +.clear-button{ + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: center; +} \ No newline at end of file diff --git a/tools/port-drayage-webservice/src/main/resources/static/css/landing.css b/tools/port-drayage-webservice/src/main/resources/static/css/landing.css new file mode 100644 index 000000000..1d163e918 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/resources/static/css/landing.css @@ -0,0 +1,31 @@ +/* Landing Page Style Sheet */ +/* */ +.main-splash{ + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: center; +} +/* Style CARMA-Streets Description */ +.main-splash-description{ + width: 80%; +} + +/* Style CARMA-Streets Logo */ +.splash-logo{ + width: 60%; + max-height: 45%; + margin-top: 20px; +} + +/* Style container holding area selection buttons */ +.area-select{ + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: center; +} +/* Style buttons to be the same size */ +.area-select-btn{ + width: 190px; +} \ No newline at end of file diff --git a/tools/port-drayage-webservice/src/main/resources/static/css/main.css b/tools/port-drayage-webservice/src/main/resources/static/css/main.css new file mode 100644 index 000000000..ba236d8aa --- /dev/null +++ b/tools/port-drayage-webservice/src/main/resources/static/css/main.css @@ -0,0 +1,77 @@ +/* Main Style Sheet */ + +/*Overwrite container class from bootstrap to occupy 100% of vertical + and horizontal space. Container contains all page content including + footer.*/ +.container{ + position: relative; + min-height: 100vh; + min-width: 100%; +} + +/*Contains all context except footer. Padding at the bottom to make room +for footer.*/ +.content-wrap { + padding-bottom: 2.5rem; +} + +/*Styling for footer panel. Split into thirds for logos, version, and copyright. + Positioned at absolute bottom. Using flex-box space around to make footer + elements be left, center and right justified.*/ +.footerPanel{ + width: 100%; + clear: both; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: space-between; + align-items: center; + position: absolute; + bottom: 0; + width: 100%; +} + +/*Footer element styling*/ +.marad-logo{ + max-height: 40px; + align-self: center; + margin-left: 10px; +} +/*Marad logo has approximately twice as much white space as FHWA logo */ +.fhwa-logo{ + max-height:80px; + align-self: center; + margin-right: 10px; +} +/* Container holding both FHWA and MARAD logos */ +.logos{ + display:flex; + width: 33%; +} +/* Copyright right aligned */ +.copyright{ + width: 33%; + text-align: right !important; + padding: 0px 10px; + font-family: Roboto; + font-weight: normal; + font-size: 80%; + color: #000000; + display: block; +} +/* Version text center aligned */ +.version { + width: 33%; + text-align: center !important; + padding: 0px 10px; + font-family: Roboto; + font-weight: normal; + font-size: 80%; + color: #000000; + display: block; + +} + + + + diff --git a/tools/port-drayage-webservice/src/main/resources/static/images/icons/inspection.png b/tools/port-drayage-webservice/src/main/resources/static/images/icons/inspection.png new file mode 100755 index 000000000..e2353d83b Binary files /dev/null and b/tools/port-drayage-webservice/src/main/resources/static/images/icons/inspection.png differ diff --git a/tools/port-drayage-webservice/src/main/resources/static/images/icons/loading.png b/tools/port-drayage-webservice/src/main/resources/static/images/icons/loading.png new file mode 100755 index 000000000..be53ffa13 Binary files /dev/null and b/tools/port-drayage-webservice/src/main/resources/static/images/icons/loading.png differ diff --git a/tools/port-drayage-webservice/src/main/resources/static/images/icons/unloading.png b/tools/port-drayage-webservice/src/main/resources/static/images/icons/unloading.png new file mode 100755 index 000000000..d0ebd94b3 Binary files /dev/null and b/tools/port-drayage-webservice/src/main/resources/static/images/icons/unloading.png differ diff --git a/tools/port-drayage-webservice/src/main/resources/static/images/logos/CARMA_Streets.png b/tools/port-drayage-webservice/src/main/resources/static/images/logos/CARMA_Streets.png new file mode 100644 index 000000000..a9e003b2e Binary files /dev/null and b/tools/port-drayage-webservice/src/main/resources/static/images/logos/CARMA_Streets.png differ diff --git a/tools/port-drayage-webservice/src/main/resources/static/images/logos/FHWALogo_2.png b/tools/port-drayage-webservice/src/main/resources/static/images/logos/FHWALogo_2.png new file mode 100644 index 000000000..376ada9f1 Binary files /dev/null and b/tools/port-drayage-webservice/src/main/resources/static/images/logos/FHWALogo_2.png differ diff --git a/tools/port-drayage-webservice/src/main/resources/static/images/logos/marad.png b/tools/port-drayage-webservice/src/main/resources/static/images/logos/marad.png new file mode 100644 index 000000000..b6b326313 Binary files /dev/null and b/tools/port-drayage-webservice/src/main/resources/static/images/logos/marad.png differ diff --git a/tools/port-drayage-webservice/src/main/resources/templates/_inspection.html b/tools/port-drayage-webservice/src/main/resources/templates/_inspection.html new file mode 100644 index 000000000..74aefae9e --- /dev/null +++ b/tools/port-drayage-webservice/src/main/resources/templates/_inspection.html @@ -0,0 +1,139 @@ +

Port Drayage Inspection Area

+
+
+
+

+ Vehicle : + + with cargo : + +

+

+
+ + + +

+ Vehicle is proceeding to Holding Area. +

+
+
+ Staging Area + Port Area +
+
+

Pending Inspections

+ + + + + + + + + + + + + + + + + + + + +
Vehicle ID Container ID Action ID Requested
No Pending Inspections
+ +

Completed Inspections

+ + + + + + + + + + + + + + + + + + + + + + + +
Vehicle ID Container ID Action ID Requested Completed
No Completed Inspection
+
+ + +
+ + \ No newline at end of file diff --git a/tools/port-drayage-webservice/src/main/resources/templates/_loading.html b/tools/port-drayage-webservice/src/main/resources/templates/_loading.html new file mode 100644 index 000000000..95247b20e --- /dev/null +++ b/tools/port-drayage-webservice/src/main/resources/templates/_loading.html @@ -0,0 +1,126 @@ +

Port Drayage Loading Area

+
+
+
+

+ Vehicle : + + with cargo : + +

+

+
+ + + +
+
+ Staging Area + Port Area +
+ +
+

Pending Loading Actions

+ + + + + + + + + + + + + + + + + + + + +
Vehicle ID Container ID Actions ID Requested
No Pending Actions
+ +

Completed Loading Actions

+ + + + + + + + + + + + + + + + + + + + + + + +
Vehicle ID Container ID Action ID Requested Completed
No Completed Actions
+
+ + +
+ + \ No newline at end of file diff --git a/tools/port-drayage-webservice/src/main/resources/templates/_unloading.html b/tools/port-drayage-webservice/src/main/resources/templates/_unloading.html new file mode 100644 index 000000000..516ac3815 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/resources/templates/_unloading.html @@ -0,0 +1,123 @@ +

Port Drayage Unloading Area

+
+
+
+

+ Vehicle : + + with cargo : + +

+

+
+ + + +
+
+ Staging Area + Port Area +
+
+

Pending Unloading Actions

+ + + + + + + + + + + + + + + + + + + + +
Vehicle ID Container ID Action ID Requested
No Pending Actions
+ +

Completed Unloading Actions

+ + + + + + + + + + + + + + + + + + + + + + + +
Vehicle ID Container ID Action ID Requested Completed
No Completed Actions
+
+ + +
+ + \ No newline at end of file diff --git a/tools/port-drayage-webservice/src/main/resources/templates/index.html b/tools/port-drayage-webservice/src/main/resources/templates/index.html new file mode 100644 index 000000000..d18e632b2 --- /dev/null +++ b/tools/port-drayage-webservice/src/main/resources/templates/index.html @@ -0,0 +1,159 @@ + + + + + + + CARMA Freight Web Service + + + + + + + +
+
+
+ + +
+
+
+
+
+ +
+ + + +
+
+
+
+ + +
+
V2X-Hub 6.2
+ +
+
+ + + + + + +
+ + + + \ No newline at end of file diff --git a/tools/port-drayage-webservice/src/main/resources/templates/landing.html b/tools/port-drayage-webservice/src/main/resources/templates/landing.html new file mode 100644 index 000000000..c51e651de --- /dev/null +++ b/tools/port-drayage-webservice/src/main/resources/templates/landing.html @@ -0,0 +1,80 @@ + + + + + + + CARMA Freight Web Service + + + + + + + + + +
+
+
+
+ +
+
+
+
+ CARMA Streets is a component of CARMA ecosystem, which enables coordination among different transportation users. + This component provides an interface for Cooperative Driving Automation (CDA) participants to interact with the road and + port infrastructure. CARMA Streets is also an edge-computing unit that improves the efficiency and performance of the + Transportation Systems Management and Operations (TSMO) strategies and Port Drayage Operations. +
+
+
+
+ + +
+
+
+
+
+ + +
+
V2X-Hub 6.2
+ +
+
+ + + + + +
+ + \ No newline at end of file diff --git a/tools/port-drayage-webservice/src/test/java/com/leidos/controller/InspectionControllerTest.java b/tools/port-drayage-webservice/src/test/java/com/leidos/controller/InspectionControllerTest.java new file mode 100644 index 000000000..9b8afb1d1 --- /dev/null +++ b/tools/port-drayage-webservice/src/test/java/com/leidos/controller/InspectionControllerTest.java @@ -0,0 +1,212 @@ +package com.leidos.controller; + +import com.baeldung.openapi.model.InspectionRequest; +import com.baeldung.openapi.model.InspectionStatus; +import com.baeldung.openapi.model.InspectionStatus.StatusEnum; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.leidos.inspection.InspectionActions; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +/** + * Test class for Inspection {@link RestController} bean + */ +@WebMvcTest(controllers = { InspectionController.class }) +public class InspectionControllerTest { + + @Autowired + private MockMvc mvc; + + @MockBean + private InspectionActions mockInspectionActions; + + private ObjectMapper mapper = new ObjectMapper(); + + /** + * Test GET /inspection {@link HttpStatus} is always OK. + * + * @throws Exception + */ + @Test + public void testGetInspection() throws Exception { + + mvc.perform(MockMvcRequestBuilders.get("/inspection/pending")).andExpect(MockMvcResultMatchers.status().isOk()); + } + + /** + * Test POST /inspection responses from {@link InspectionController}. + * + * @throws Exception + */ + @Test + public void testPostInspection() throws Exception { + + // Test response for valid payload + InspectionRequest request = new InspectionRequest(); + request.setVehicleId("vehicleId"); + request.setContainerId("containerId"); + request.setActionId("actionId"); + + mvc.perform(MockMvcRequestBuilders.post("/inspection").contentType(MediaType.APPLICATION_JSON) + .content(mapper.writeValueAsString(request))).andExpect(MockMvcResultMatchers.status().isCreated()); + + // Test response for empty post + mvc.perform(MockMvcRequestBuilders.post("/inspection").contentType(MediaType.APPLICATION_JSON).content("")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + + // Test response for invalid post + mvc.perform(MockMvcRequestBuilders.post("/inspection").contentType(MediaType.APPLICATION_JSON) + .content("{ \"invalid\": \"json\"}")).andExpect(MockMvcResultMatchers.status().isBadRequest()); + + // Mock duplicate request + InspectionStatus responseStatus = new InspectionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(InspectionStatus.StatusEnum.PROCEED_TO_HOLDING); + responseStatus.setRequested(System.currentTimeMillis()); + + // Mock already existing action for action ID + Mockito.when(mockInspectionActions.getInspectionStatus(responseStatus.getActionId())) + .thenReturn(responseStatus); + + mvc.perform(MockMvcRequestBuilders.post("/inspection").contentType(MediaType.APPLICATION_JSON) + .content(mapper.writeValueAsString(request))).andExpect(MockMvcResultMatchers.status().isBadRequest()); + + } + + /** + * Test POST /inspection/holding responses from {@link InspectionController}. + * + * @throws Exception + */ + @Test + public void testPostInspectionHolding() throws Exception { + + // Mock inspectionAction to have current action + InspectionStatus responseStatus = new InspectionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(InspectionStatus.StatusEnum.PROCEED_TO_HOLDING); + responseStatus.setRequested(System.currentTimeMillis()); + + // Mock current inspection + Mockito.when(mockInspectionActions.getCurrentInspection()).thenReturn(responseStatus); + Mockito.when(mockInspectionActions.getInspectionStatus("actionId")).thenReturn(responseStatus); + + // Test response for valid payload + InspectionRequest request = new InspectionRequest(); + request.setVehicleId("vehicleId"); + request.setContainerId("containerId"); + request.setActionId("actionId"); + + // Correct + mvc.perform(MockMvcRequestBuilders.post("/inspection/holding/" + request.getActionId()) + .contentType(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isCreated()); + mvc.perform(MockMvcRequestBuilders.post("/inspection/holding/" + request.getActionId()) + .contentType(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isCreated()); + + // Test response for non current action ( both incorrect vehicle and container + // id) + request.setActionId("wrong"); + mvc.perform(MockMvcRequestBuilders.post("/inspection/holding/" + request.getActionId()) + .contentType(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isBadRequest()); + + // Test response for invalid post + mvc.perform(MockMvcRequestBuilders.post("/inspection").contentType(MediaType.APPLICATION_JSON) + .content("{ \"invalid\": \"json\"}")).andExpect(MockMvcResultMatchers.status().isBadRequest()); + + } + + /** + * Test GET /inspection/{vehicleId} responses from {@link InspectionController}. + * + * @throws Exception + */ + @Test + public void testInspectionVehicleIdGet() throws Exception { + + InspectionStatus responseStatus = new InspectionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setStatus(InspectionStatus.StatusEnum.PENDING); + responseStatus.setRequested(System.currentTimeMillis()); + + Mockito.when(mockInspectionActions.getInspectionStatus("vehicleId")).thenReturn(responseStatus); + + // Test response for get loading/{vehicleId} for existing request + mvc.perform(MockMvcRequestBuilders.get("/inspection/vehicleId")) + .andExpect(MockMvcResultMatchers.status().isOk()); + mvc.perform(MockMvcRequestBuilders.get("/inspection/vehicleId")) + .andExpect(MockMvcResultMatchers.content().json(mapper.writeValueAsString(responseStatus))); + + // Test response for get loading/{vehicleId} for non-existent request + mvc.perform(MockMvcRequestBuilders.get("/inspection/no-existent")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + /** + * Test inspection/complete/{action_id} POST + */ + @Test + public void testInspectionCompleteActionIdPost() throws Exception { + // Create current action + InspectionStatus responseStatus = new InspectionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(StatusEnum.PENDING); + responseStatus.setRequested(System.currentTimeMillis()); + + // Mock return responseStatus as current action + Mockito.when(mockInspectionActions.getCurrentInspection()).thenReturn(responseStatus); + Mockito.when(mockInspectionActions.getInspectionStatus(responseStatus.getActionId())) + .thenReturn(responseStatus); + + // Assert 201 response when current action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/inspection/complete/{actionId}", responseStatus.getActionId())) + .andExpect(MockMvcResultMatchers.status().isCreated()); + + // Assert 400 response when incorrect action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/inspection/complete/{actionId}", "wrong")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + + } + + /** + * Test inspection/hold/{action_id} POST + */ + @Test + public void testInspectionHoldActionIdPost() throws Exception { + // Create current action + InspectionStatus responseStatus = new InspectionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(StatusEnum.PENDING); + responseStatus.setRequested(System.currentTimeMillis()); + + // Mock return responseStatus as current action + Mockito.when(mockInspectionActions.getCurrentInspection()).thenReturn(responseStatus); + Mockito.when(mockInspectionActions.getInspectionStatus(responseStatus.getActionId())) + .thenReturn(responseStatus); + + // Assert 201 response when current action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/inspection/hold/{actionId}", responseStatus.getActionId())) + .andExpect(MockMvcResultMatchers.status().isCreated()); + + // Assert 400 response when incorrect action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/inspection/hold/{actionId}", "wrong")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + + } +} diff --git a/tools/port-drayage-webservice/src/test/java/com/leidos/controller/LoadingControllerTest.java b/tools/port-drayage-webservice/src/test/java/com/leidos/controller/LoadingControllerTest.java new file mode 100644 index 000000000..d37a5f68d --- /dev/null +++ b/tools/port-drayage-webservice/src/test/java/com/leidos/controller/LoadingControllerTest.java @@ -0,0 +1,159 @@ +package com.leidos.controller; + +import com.baeldung.openapi.model.ContainerActionStatus; +import com.baeldung.openapi.model.ContainerRequest; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.leidos.loading.LoadingActions; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@WebMvcTest(controllers = { LoadingController.class }) +public class LoadingControllerTest { + + @Autowired + private MockMvc mvc; + + @MockBean + private LoadingActions mockLoadingActions; + + private ObjectMapper mapper = new ObjectMapper(); + + /** + * Test GET /loading {@link HttpStatus} is always OK. + * + * @throws Exception + */ + @Test + public void testGetLoading() throws Exception { + + mvc.perform(MockMvcRequestBuilders.get("/loading/pending")).andExpect(MockMvcResultMatchers.status().isOk()); + } + + /** + * Test POST /loading responses from {@link LoadingController}. + * + * @throws Exception + */ + @Test + public void testPostLoading() throws Exception { + + // Test response for valid payload + ContainerRequest request = new ContainerRequest(); + request.setVehicleId("vehicleId"); + request.setContainerId("containerId"); + request.setActionId("actionId"); + + mvc.perform(MockMvcRequestBuilders.post("/loading").contentType(MediaType.APPLICATION_JSON) + .content(mapper.writeValueAsString(request))).andExpect(MockMvcResultMatchers.status().isCreated()); + + // Test response for empty post + mvc.perform(MockMvcRequestBuilders.post("/loading").contentType(MediaType.APPLICATION_JSON).content("")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + + // Test response for invalid post + mvc.perform(MockMvcRequestBuilders.post("/loading").contentType(MediaType.APPLICATION_JSON) + .content("{ \"invalid\": \"json\"}")).andExpect(MockMvcResultMatchers.status().isBadRequest()); + + // Mock already existing duplicate action + ContainerActionStatus responseStatus = new ContainerActionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(ContainerActionStatus.StatusEnum.LOADING); + responseStatus.setRequested(System.currentTimeMillis()); + Mockito.when(mockLoadingActions.getContainerActionStatus(responseStatus.getActionId())) + .thenReturn(responseStatus); + + mvc.perform(MockMvcRequestBuilders.post("/loading").contentType(MediaType.APPLICATION_JSON) + .content(mapper.writeValueAsString(request))).andExpect(MockMvcResultMatchers.status().isBadRequest()); + + } + + /** + * Test GET /loading/{vehicleId} responses from {@link LoadingController}. + * + * @throws Exception + */ + @Test + public void testLoadingVehicleIdGet() throws Exception { + + ContainerActionStatus responseStatus = new ContainerActionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(ContainerActionStatus.StatusEnum.LOADING); + responseStatus.setRequested(System.currentTimeMillis()); + + Mockito.when(mockLoadingActions.getContainerActionStatus("vehicleId")).thenReturn(responseStatus); + + // Test response for get loading/{vehicleId} for existing request + mvc.perform(MockMvcRequestBuilders.get("/loading/vehicleId")).andExpect(MockMvcResultMatchers.status().isOk()); + mvc.perform(MockMvcRequestBuilders.get("/loading/vehicleId")) + .andExpect(MockMvcResultMatchers.content().json(mapper.writeValueAsString(responseStatus))); + + // Test response for get loading/{vehicleId} for non-existent request + mvc.perform(MockMvcRequestBuilders.get("/loading/no-existent")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + /** + * Test loading/complete/{action_id} POST + */ + @Test + public void testLoadingCompleteActionIdPost() throws Exception { + // Create current action + ContainerActionStatus responseStatus = new ContainerActionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(ContainerActionStatus.StatusEnum.PENDING); + responseStatus.setRequested(System.currentTimeMillis()); + + // Mock return responseStatus as current action + Mockito.when(mockLoadingActions.getCurrentAction()).thenReturn(responseStatus); + + // Assert 201 response when current action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/loading/complete/{actionId}", responseStatus.getActionId())) + .andExpect(MockMvcResultMatchers.status().isCreated()); + + // Assert 400 response when incorrect action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/loading/complete/{actionId}", "wrong")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + + } + + /** + * Test unloading/start/{action_id} POST + */ + @Test + public void testUnloadingStartActionIdPost() throws Exception { + // Create current action + ContainerActionStatus responseStatus = new ContainerActionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(ContainerActionStatus.StatusEnum.PENDING); + responseStatus.setRequested(System.currentTimeMillis()); + + // Mock return responseStatus as current action + Mockito.when(mockLoadingActions.getCurrentAction()).thenReturn(responseStatus); + + // Assert 201 response when current action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/loading/start/{actionId}", responseStatus.getActionId())) + .andExpect(MockMvcResultMatchers.status().isCreated()); + + // Assert 400 response when incorrect action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/loading/start/{actionId}", "wrong")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + + } + +} diff --git a/tools/port-drayage-webservice/src/test/java/com/leidos/controller/UnloadingControllerTest.java b/tools/port-drayage-webservice/src/test/java/com/leidos/controller/UnloadingControllerTest.java new file mode 100644 index 000000000..9ae3e4751 --- /dev/null +++ b/tools/port-drayage-webservice/src/test/java/com/leidos/controller/UnloadingControllerTest.java @@ -0,0 +1,160 @@ +package com.leidos.controller; + +import com.baeldung.openapi.model.ContainerActionStatus; +import com.baeldung.openapi.model.ContainerRequest; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.leidos.unloading.UnloadingActions; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@WebMvcTest(controllers = { UnloadingController.class }) +public class UnloadingControllerTest { + + @Autowired + private MockMvc mvc; + + @MockBean + private UnloadingActions mockUnloadingActions; + + private ObjectMapper mapper = new ObjectMapper(); + + /** + * Test GET /unloading {@link HttpStatus} is always OK. + * + * @throws Exception + */ + @Test + public void testGetUnloading() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/unloading/pending")).andExpect(MockMvcResultMatchers.status().isOk()); + } + + /** + * Test POST /unloading responses from {@link UnloadingController}. + * + * @throws Exception + */ + @Test + public void testPostUnloading() throws Exception { + + // Test response for valid payload + ContainerRequest request = new ContainerRequest(); + request.setVehicleId("vehicleId"); + request.setContainerId("containerId"); + request.setActionId("actionId"); + + mvc.perform(MockMvcRequestBuilders.post("/unloading").contentType(MediaType.APPLICATION_JSON) + .content(mapper.writeValueAsString(request))).andExpect(MockMvcResultMatchers.status().isCreated()); + + // Test response for empty post + mvc.perform(MockMvcRequestBuilders.post("/unloading").contentType(MediaType.APPLICATION_JSON).content("")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + + // Test response for invalid post + mvc.perform(MockMvcRequestBuilders.post("/unloading").contentType(MediaType.APPLICATION_JSON) + .content("{ \"invalid\": \"json\"}")).andExpect(MockMvcResultMatchers.status().isBadRequest()); + + // Mock already existing duplicate action + ContainerActionStatus responseStatus = new ContainerActionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(ContainerActionStatus.StatusEnum.UNLOADING); + responseStatus.setRequested(System.currentTimeMillis()); + Mockito.when(mockUnloadingActions.getContainerActionStatus(responseStatus.getActionId())) + .thenReturn(responseStatus); + + mvc.perform(MockMvcRequestBuilders.post("/unloading").contentType(MediaType.APPLICATION_JSON) + .content(mapper.writeValueAsString(request))).andExpect(MockMvcResultMatchers.status().isBadRequest()); + + } + + /** + * Test GET /unloading/{vehicleId} responses from {@link UnloadingController}. + * + * @throws Exception + */ + @Test + public void testUnloadingVehicleIdGet() throws Exception { + + ContainerActionStatus responseStatus = new ContainerActionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(ContainerActionStatus.StatusEnum.UNLOADING); + responseStatus.setRequested(System.currentTimeMillis()); + + Mockito.when(mockUnloadingActions.getContainerActionStatus(responseStatus.getActionId())) + .thenReturn(responseStatus); + + // Test response for get loading/{vehicleId} for existing request + mvc.perform(MockMvcRequestBuilders.get("/unloading/actionId")) + .andExpect(MockMvcResultMatchers.status().isOk()); + mvc.perform(MockMvcRequestBuilders.get("/unloading/actionId")) + .andExpect(MockMvcResultMatchers.content().json(mapper.writeValueAsString(responseStatus))); + + // Test response for get loading/{vehicleId} for non-existent request + mvc.perform(MockMvcRequestBuilders.get("/unloading/no-existent")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + } + + /** + * Test unloading/complete/{action_id} POST + */ + @Test + public void testUnloadingCompleteActionIdPost() throws Exception { + // Create current action + ContainerActionStatus responseStatus = new ContainerActionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(ContainerActionStatus.StatusEnum.PENDING); + responseStatus.setRequested(System.currentTimeMillis()); + + // Mock return responseStatus as current action + Mockito.when(mockUnloadingActions.getCurrentAction()).thenReturn(responseStatus); + + // Assert 201 response when current action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/unloading/complete/{actionId}", responseStatus.getActionId())) + .andExpect(MockMvcResultMatchers.status().isCreated()); + + // Assert 400 response when incorrect action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/unloading/complete/{actionId}", "wrong")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + + } + + /** + * Test unloading/start/{action_id} POST + */ + @Test + public void testUnloadingStartActionIdPost() throws Exception { + // Create current action + ContainerActionStatus responseStatus = new ContainerActionStatus(); + responseStatus.setContainerId("containerId"); + responseStatus.setVehicleId("vehicleId"); + responseStatus.setActionId("actionId"); + responseStatus.setStatus(ContainerActionStatus.StatusEnum.PENDING); + responseStatus.setRequested(System.currentTimeMillis()); + + // Mock return responseStatus as current action + Mockito.when(mockUnloadingActions.getCurrentAction()).thenReturn(responseStatus); + + // Assert 201 response when current action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/unloading/start/{actionId}", responseStatus.getActionId())) + .andExpect(MockMvcResultMatchers.status().isCreated()); + + // Assert 400 response when incorrect action ID is provided + mvc.perform(MockMvcRequestBuilders.post("/unloading/start/{actionId}", "wrong")) + .andExpect(MockMvcResultMatchers.status().isBadRequest()); + + } + +} diff --git a/tools/port-drayage-webservice/src/test/java/com/leidos/inspection/InspectionActionsTest.java b/tools/port-drayage-webservice/src/test/java/com/leidos/inspection/InspectionActionsTest.java new file mode 100644 index 000000000..304a5c5f2 --- /dev/null +++ b/tools/port-drayage-webservice/src/test/java/com/leidos/inspection/InspectionActionsTest.java @@ -0,0 +1,194 @@ +package com.leidos.inspection; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.baeldung.openapi.model.InspectionRequest; +import com.baeldung.openapi.model.InspectionStatus; +import com.baeldung.openapi.model.InspectionStatus.StatusEnum; + +import org.junit.jupiter.api.BeforeEach; + +/** + * Test Class to test {@link InspectionActions} class. + * + * @author Paul Bourelly + */ +public class InspectionActionsTest { + + private InspectionActions inspectionActions; + + /** + * Init to run before each test + */ + @BeforeEach + public void init() { + // Initialize Inspection Action Bean + inspectionActions = new InspectionActions(); + } + + /** + * Test case to test {@link InspectionActions#getInspectionStatus(String)} and + * {@link InspectionActions#requestInspectionAction(InspectionRequest)} for + * different possible inputs. + */ + @Test + public void requestInspectionTest() { + // Returns null when provided null vehicleId + assertNull(inspectionActions.getInspectionStatus(null)); + + // requestInspectionAction does not throw exceptions for null parameters + inspectionActions.requestInspectionAction(null); + + // Populate Inspection actions with inspection requests + InspectionRequest req1 = new InspectionRequest(); + req1.setVehicleId("vehicleA"); + req1.setContainerId("containerA"); + req1.setActionId("inspectionA"); + + // Returns null before inspection is requested + assertNull(inspectionActions.getInspectionStatus(req1.getActionId())); + assertNull(inspectionActions.getCurrentInspection()); + + // Current action and inspection status returns action after inspection is + // requested + inspectionActions.requestInspectionAction(req1); + assertEquals(req1.getVehicleId(), inspectionActions.getCurrentInspection().getVehicleId()); + assertEquals(req1.getContainerId(), inspectionActions.getCurrentInspection().getContainerId()); + assertEquals(req1.getVehicleId(), inspectionActions.getInspectionStatus(req1.getActionId()).getVehicleId()); + assertEquals(req1.getContainerId(), inspectionActions.getInspectionStatus(req1.getActionId()).getContainerId()); + + // Attempt to request new inspection while another inspection is in progress + InspectionRequest req2 = new InspectionRequest(); + req2.setVehicleId("vehicleC"); + req2.setContainerId("containerC"); + req2.setActionId("inspectionC"); + inspectionActions.requestInspectionAction(req2); + InspectionStatus status = inspectionActions.getCurrentInspection(); + + // Current Action is still first request + assertEquals(req1.getContainerId(), status.getContainerId()); + assertEquals(req1.getVehicleId(), status.getVehicleId()); + + // New inspection request is in pending inspection list + InspectionStatus pending = inspectionActions.getPendingInspections().getInspections().get(0); + assertEquals(req2.getVehicleId(), pending.getVehicleId()); + assertEquals(req2.getContainerId(), pending.getContainerId()); + } + + /** + * Test case to test {@link InspectionActions#completeInspection()} for + * different possible parameters. + */ + @Test + public void completeInspectionTest() { + // Populate Inspection actions with inspection requests + InspectionRequest req1 = new InspectionRequest(); + req1.setVehicleId("vehicleA"); + req1.setContainerId("containerA"); + req1.setActionId("inspectionA"); + + InspectionRequest req2 = new InspectionRequest(); + req2.setVehicleId("vehicleB"); + req2.setContainerId("containerB"); + req2.setActionId("inspectionB"); + + InspectionRequest req3 = new InspectionRequest(); + req3.setVehicleId("vehicleC"); + req3.setContainerId("containerC"); + req3.setActionId("inspectionC"); + + // Calling complete inspection with no current inspection does not add any + // inspection to completed list + inspectionActions.completeInspection(); + assertNull(inspectionActions.getCompletedInspections().getInspections()); + + inspectionActions.requestInspectionAction(req1); + inspectionActions.requestInspectionAction(req2); + inspectionActions.requestInspectionAction(req3); + + // Completed Inspections is empty before completing any inspection but + // inspection is in inspectionActions list of in progress inspections + assertNull(inspectionActions.getCompletedInspections().getInspections()); + + InspectionStatus req1Status = inspectionActions.getInspectionStatus(req1.getActionId()); + InspectionStatus req2Status = inspectionActions.getInspectionStatus(req2.getActionId()); + InspectionStatus req3Status = inspectionActions.getInspectionStatus(req3.getActionId()); + + // First request becomes current action and additional requests are added to + // pending inspections + assertEquals(req1Status, inspectionActions.getCurrentInspection()); + assertTrue(inspectionActions.getPendingInspections().getInspections().contains(req2Status)); + assertTrue(inspectionActions.getPendingInspections().getInspections().contains(req3Status)); + + // Complete inspection adds current inspection to completedInspections list and + // sets next pending action as currentAction + inspectionActions.completeInspection(); + + assertTrue(inspectionActions.getCompletedInspections().getInspections().contains(req1Status)); + assertEquals(req2Status, inspectionActions.getCurrentInspection()); + assertTrue(inspectionActions.getPendingInspections().getInspections().contains(req3Status)); + assertNotNull(req1Status.getCompleted()); + assertEquals(InspectionStatus.StatusEnum.PASSED, req1Status.getStatus()); + + // Completing inspection when no pending actions are left sets current action to + // null + // req2Status + inspectionActions.completeInspection(); + + // req3Status + inspectionActions.completeInspection(); + + assertNull(inspectionActions.getCurrentInspection()); + assertEquals(3, inspectionActions.getCompletedInspections().getInspections().size()); + + // Get InspectionStatus will return most recent inspection even when it is completed + // for a given vehicleID + assertEquals(req3Status, inspectionActions.getInspectionStatus(req3.getActionId())); + } + + /** + * Test case to test {@link InspectionActions#requestHolding()} method and + * holding vehicle interactions. + */ + @Test + public void requestHoldingTest() { + // Populate Inspection actions with inspection requests + InspectionRequest req1 = new InspectionRequest(); + req1.setVehicleId("vehicleA"); + req1.setContainerId("containerA"); + + // Call proceed to holding with no current action + assertNull(inspectionActions.getCurrentInspection()); + inspectionActions.proceedToHolding(); + + // Call request holding with to current action + inspectionActions.requestHolding(); + assertNull(inspectionActions.getCurrentInspection()); + + // Request Inspection + inspectionActions.requestInspectionAction(req1); + InspectionStatus req1Status = inspectionActions.getCurrentInspection(); + + assertEquals(StatusEnum.PENDING, req1Status.getStatus() ); + + // Proceed To Holding + inspectionActions.proceedToHolding(); + + assertEquals(StatusEnum.PROCEED_TO_HOLDING, req1Status.getStatus() ); + + // Request Holding + inspectionActions.requestHolding(); + + assertEquals(StatusEnum.HOLDING, req1Status.getStatus() ); + + // Complete + inspectionActions.completeInspection(); + assertEquals(StatusEnum.PASSED, req1Status.getStatus() ); + + } +} diff --git a/tools/port-drayage-webservice/src/test/java/com/leidos/loading/LoadingActionsTest.java b/tools/port-drayage-webservice/src/test/java/com/leidos/loading/LoadingActionsTest.java new file mode 100644 index 000000000..dae1c3400 --- /dev/null +++ b/tools/port-drayage-webservice/src/test/java/com/leidos/loading/LoadingActionsTest.java @@ -0,0 +1,155 @@ +package com.leidos.loading; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.baeldung.openapi.model.ContainerActionStatus; +import com.baeldung.openapi.model.ContainerRequest; +import com.baeldung.openapi.model.ContainerActionStatus.StatusEnum; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class LoadingActionsTest { + + public LoadingActions loadingActions; + + /** + * Init to run before each test + */ + @BeforeEach + public void init() { + // Initialize Inspection Action Bean + loadingActions = new LoadingActions(); + } + + /** + * Test case to test {@link LoadingActions#getContainerActionStatus(String)} and + * {@link LoadingActions#requestLoadingAction(ContainerRequest)} for different + * possible inputs. + */ + @Test + public void requestLoadingActionTest() { + // Returns null when provided null vehicleId + assertNull(loadingActions.getContainerActionStatus(null)); + + // requestLoadingAction does not throw exceptions for null parameters + loadingActions.requestLoadingAction(null); + + // Populate Loading actions with Loading requests + ContainerRequest req1 = new ContainerRequest(); + req1.setVehicleId("vehicleA"); + req1.setContainerId("containerA"); + req1.setActionId("actionA"); + + // Returns null before loading action is requested + assertNull(loadingActions.getContainerActionStatus(req1.getActionId())); + assertNull(loadingActions.getCurrentAction()); + + // Returns action after loading action is requested + loadingActions.requestLoadingAction(req1); + assertEquals(req1.getVehicleId(), loadingActions.getCurrentAction().getVehicleId()); + assertEquals(req1.getContainerId(), loadingActions.getCurrentAction().getContainerId()); + + // Attempt to request new loading action for vehicle with already pending + // loading action + ContainerRequest req2 = new ContainerRequest(); + req2.setVehicleId("vehicleA"); + req2.setContainerId("containerC"); + req2.setActionId("actionC"); + loadingActions.requestLoadingAction(req2); + ContainerActionStatus status = loadingActions.getCurrentAction(); + assertEquals(req1.getContainerId(), status.getContainerId()); + } + + /** + * Test case to test + * {@link LoadingAction#completeCurrentAction(com.baeldung.openapi.model.ContainerActionStatus)} + * for different possible parameters. + */ + @Test + public void completeLoadingTest() { + // Populate loading actions with loading requests + ContainerRequest req1 = new ContainerRequest(); + req1.setVehicleId("vehicleA"); + req1.setContainerId("containerA"); + req1.setActionId("actionA"); + + ContainerRequest req2 = new ContainerRequest(); + req2.setVehicleId("vehicleB"); + req2.setContainerId("containerB"); + req2.setActionId("actionB"); + + ContainerRequest req3 = new ContainerRequest(); + req3.setVehicleId("vehicleC"); + req3.setContainerId("containerC"); + req3.setActionId("actionC"); + + // Run completeCurrentAction with no current action + assertNull(loadingActions.getCurrentAction()); + loadingActions.completeCurrentAction(); + + // Run startCurrentAction with no current action + assertNull(loadingActions.getCurrentAction()); + loadingActions.startCurrentAction(); + + loadingActions.requestLoadingAction(req1); + loadingActions.requestLoadingAction(req2); + loadingActions.requestLoadingAction(req3); + + // Completed actions is empty before completing any loading action but + // loading action is in loadingActions list of in progress actions + assertNull(loadingActions.getCompletedActions().getActions()); + ContainerActionStatus req1Status = loadingActions.getContainerActionStatus(req1.getActionId()); + ContainerActionStatus req2Status = loadingActions.getContainerActionStatus(req2.getActionId()); + ContainerActionStatus req3Status = loadingActions.getContainerActionStatus(req3.getActionId()); + + // First requested action becomes current action and each action requested after + // is added to + // pending actions + assertEquals(req1Status, loadingActions.getCurrentAction()); + assertTrue(loadingActions.getPendingActions().getActions().contains(req2Status)); + assertTrue(loadingActions.getPendingActions().getActions().contains(req3Status)); + + + + // Start current action sets status to LOADING + assertEquals(StatusEnum.PENDING, loadingActions.getCurrentAction().getStatus()); + loadingActions.startCurrentAction(); + assertEquals(StatusEnum.LOADING, loadingActions.getCurrentAction().getStatus()); + + // Current action status is set to LOADED and added to completedActions list. + // Current action is replaced with next action in pending actions + // Complete req1 + loadingActions.completeCurrentAction(); + + assertTrue(loadingActions.getCompletedActions().getActions().contains(req1Status)); + assertNotNull(req1Status.getCompleted()); + assertEquals(ContainerActionStatus.StatusEnum.LOADED, req1Status.getStatus()); + assertEquals(req2Status, loadingActions.getCurrentAction()); + + // Complete req2 + loadingActions.completeCurrentAction(); + + assertTrue(loadingActions.getCompletedActions().getActions().contains(req2Status)); + assertNotNull(req2Status.getCompleted()); + assertEquals(ContainerActionStatus.StatusEnum.LOADED, req2Status.getStatus()); + assertEquals(req3Status, loadingActions.getCurrentAction()); + assertTrue(loadingActions.getPendingActions().getActions().isEmpty()); + + // Complete req3 + loadingActions.completeCurrentAction(); + + assertNull(loadingActions.getCurrentAction()); + assertEquals(3, loadingActions.getCompletedActions().getActions().size()); + + // Get ContainerActionStatus will return most recent action even when it is + // completed + // for a given vehicleID + assertEquals(req3Status, loadingActions.getContainerActionStatus(req3.getActionId())); + + } +} diff --git a/tools/port-drayage-webservice/src/test/java/com/leidos/unloading/UnloadingActionsTest.java b/tools/port-drayage-webservice/src/test/java/com/leidos/unloading/UnloadingActionsTest.java new file mode 100644 index 000000000..edb0e47ce --- /dev/null +++ b/tools/port-drayage-webservice/src/test/java/com/leidos/unloading/UnloadingActionsTest.java @@ -0,0 +1,150 @@ +package com.leidos.unloading; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.baeldung.openapi.model.ContainerActionStatus; +import com.baeldung.openapi.model.ContainerRequest; +import com.baeldung.openapi.model.ContainerActionStatus.StatusEnum; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class UnloadingActionsTest { + public UnloadingActions unloadingActions; + + /** + * Init to run before each test + */ + @BeforeEach + public void init() { + // Initialize Inspection Action Bean + unloadingActions = new UnloadingActions(); + } + + /** + * Test case to test {@link UnloadingActions#getContainerActionStatus(String)} + * and {@link UnloadingActions#requestUnloadingAction(ContainerRequest)} for + * different possible inputs. + */ + @Test + public void requestLoadingActionTest() { + // Returns null when provided null vehicleId + assertNull(unloadingActions.getContainerActionStatus(null)); + + // requestLoadingAction does not throw exceptions for null parameters + unloadingActions.requestUnloadingAction(null); + + // Populate unloading actions with unloading requests + ContainerRequest req1 = new ContainerRequest(); + req1.setVehicleId("vehicleA"); + req1.setContainerId("containerA"); + req1.setActionId("actionA"); + + // Returns null before unloading action is requested + assertNull(unloadingActions.getContainerActionStatus(req1.getActionId())); + + // Returns action after unloading action is requested + unloadingActions.requestUnloadingAction(req1); + assertEquals(req1.getVehicleId(), unloadingActions.getCurrentAction().getVehicleId()); + assertEquals(req1.getContainerId(), unloadingActions.getCurrentAction().getContainerId()); + + // Attempt to request new unloading action with already pending + // unloading action + ContainerRequest req2 = new ContainerRequest(); + req2.setVehicleId("vehicleC"); + req2.setContainerId("containerC"); + req2.setActionId("actionC"); + unloadingActions.requestUnloadingAction(req2); + ContainerActionStatus status = unloadingActions.getCurrentAction(); + assertEquals(req1.getContainerId(), status.getContainerId()); + } + + /** + * Test case to test + * {@link LoadingAction#completeCurrentAction(ContainerActionStatus)} for + * different possible parameters. + */ + @Test + public void completeLoadingTest() { + // Populate loading actions with loading requests + ContainerRequest req1 = new ContainerRequest(); + req1.setVehicleId("vehicleA"); + req1.setContainerId("containerA"); + req1.setActionId("actionA"); + + ContainerRequest req2 = new ContainerRequest(); + req2.setVehicleId("vehicleB"); + req2.setContainerId("containerB"); + req2.setActionId("actionB"); + + ContainerRequest req3 = new ContainerRequest(); + req3.setVehicleId("vehicleC"); + req3.setContainerId("containerC"); + req3.setActionId("actionC"); + + // Run completeCurrentAction with no current action + assertNull(unloadingActions.getCurrentAction()); + unloadingActions.completeCurrentAction(); + + // Run startCurrentAction with no current action + assertNull(unloadingActions.getCurrentAction()); + unloadingActions.startCurrentAction(); + + unloadingActions.requestUnloadingAction(req1); + unloadingActions.requestUnloadingAction(req2); + unloadingActions.requestUnloadingAction(req3); + + // Completed actions is empty before completing any loading action but + // loading action is in unloadingActions list of in progress actions + assertNull(unloadingActions.getCompletedActions().getActions()); + ContainerActionStatus req1Status = unloadingActions.getContainerActionStatus(req1.getActionId()); + ContainerActionStatus req2Status = unloadingActions.getContainerActionStatus(req2.getActionId()); + ContainerActionStatus req3Status = unloadingActions.getContainerActionStatus(req3.getActionId()); + + // First requested action becomes current action and each action requested after + // is added to + // pending actions + assertEquals(req1Status, unloadingActions.getCurrentAction()); + assertTrue(unloadingActions.getPendingActions().getActions().contains(req2Status)); + assertTrue(unloadingActions.getPendingActions().getActions().contains(req3Status)); + + // Start current action sets status to UNLOADING + assertEquals(StatusEnum.PENDING, unloadingActions.getCurrentAction().getStatus()); + unloadingActions.startCurrentAction(); + assertEquals(StatusEnum.UNLOADING, unloadingActions.getCurrentAction().getStatus()); + + // Current action status is set to UNLOADED and added to completedActions list. + // Current action is replaced with next action in pending actions + // Complete req1 + unloadingActions.completeCurrentAction(); + + assertTrue(unloadingActions.getCompletedActions().getActions().contains(req1Status)); + assertNotNull(req1Status.getCompleted()); + assertEquals(ContainerActionStatus.StatusEnum.UNLOADED, req1Status.getStatus()); + assertEquals(req2Status, unloadingActions.getCurrentAction()); + + // Complete req2 + unloadingActions.completeCurrentAction(); + + assertTrue(unloadingActions.getCompletedActions().getActions().contains(req2Status)); + assertNotNull(req2Status.getCompleted()); + assertEquals(ContainerActionStatus.StatusEnum.UNLOADED, req2Status.getStatus()); + assertEquals(req3Status, unloadingActions.getCurrentAction()); + assertTrue(unloadingActions.getPendingActions().getActions().isEmpty()); + + // Complete req3 + unloadingActions.completeCurrentAction(); + + assertNull(unloadingActions.getCurrentAction()); + assertEquals(3, unloadingActions.getCompletedActions().getActions().size()); + + // Get ContainerActionStatus will return most recent action even when it is + // completed + // for a given vehicleID + assertEquals(req3Status, unloadingActions.getContainerActionStatus(req3.getActionId())); + } +}