473 lines
21 KiB
C
473 lines
21 KiB
C
#include "evm.h"
|
|
#include "facilities.h"
|
|
|
|
#include <fcntl.h>
|
|
#include <it2s-asn/etsi-its-v1/evcsnm/EI1_EvcsnPdu.h>
|
|
#include <it2s-asn/etsi-its-sdu/itss-facilities/EIS_FacilitiesIndication.h>
|
|
#include <it2s-asn/etsi-its-sdu/itss-management/EIS_ManagementRequest.h>
|
|
#include <it2s-asn/etsi-its-sdu/itss-networking/EIS_NetworkingRequest.h>
|
|
#include <it2s-tender/constants.h>
|
|
#include <it2s-tender/database.h>
|
|
#include <it2s-tender/packet.h>
|
|
#include <it2s-tender/recorder.h>
|
|
#include <it2s-tender/space.h>
|
|
#include <it2s-tender/time.h>
|
|
#include <math.h>
|
|
#include <stdint.h>
|
|
#include <sys/mman.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <zmq.h>
|
|
|
|
|
|
static UTF8String_t *create_utf8_from_string(const char *string, size_t length) {
|
|
UTF8String_t *utf8_string = calloc(1, sizeof(UTF8String_t));
|
|
utf8_string->buf = calloc(length, sizeof(uint8_t));
|
|
utf8_string->size = length;
|
|
memcpy(utf8_string->buf, string, length);
|
|
return utf8_string;
|
|
}
|
|
|
|
static UTF8String_t *create_empty_utf8_string() {
|
|
UTF8String_t *utf8_string = calloc(1, sizeof(UTF8String_t));
|
|
utf8_string->size = 0;
|
|
return utf8_string;
|
|
}
|
|
|
|
static int mk_evcsnm(uint8_t *evcsnm_oer, uint32_t *evcsnm_len) {
|
|
int rv = 0;
|
|
int shm_fd, shm_valid = 0;
|
|
|
|
EI1_EvcsnPdu_t *evcsnm = calloc(1, sizeof(EI1_EvcsnPdu_t));
|
|
evcsnm->header.protocolVersion = 2;
|
|
evcsnm->header.messageID = 1;
|
|
pthread_mutex_lock(&facilities.id.lock);
|
|
evcsnm->header.stationID = facilities.id.station_id;
|
|
pthread_mutex_unlock(&facilities.id.lock);
|
|
|
|
uint64_t now = itss_time_get();
|
|
asn_ulong2INTEGER(&evcsnm->evcsn.poiHeader.timeStamp, now);
|
|
evcsnm->evcsn.poiHeader.poiType = 1; // set to "EV charging station POI ID = 1"
|
|
evcsnm->evcsn.poiHeader.relayCapable = 1;
|
|
|
|
evcsnm->evcsn.evcsnData.totalNumberOfStations = 1;
|
|
evcsnm->evcsn.evcsnData.chargingStationsData.list.array = calloc(1, sizeof(void *));
|
|
evcsnm->evcsn.evcsnData.chargingStationsData.list.count = 1;
|
|
evcsnm->evcsn.evcsnData.chargingStationsData.list.size = sizeof(void *) * 1;
|
|
evcsnm->evcsn.evcsnData.chargingStationsData.list.array[0] = calloc(1, sizeof(struct EI1_ItsChargingStationData));
|
|
struct EI1_ItsChargingStationData *cs0 = evcsnm->evcsn.evcsnData.chargingStationsData.list.array[0];
|
|
cs0->chargingStationID = 0;
|
|
itss_space_lock();
|
|
itss_space_get();
|
|
cs0->chargingStationLocation.latitude = 405970830;
|
|
cs0->chargingStationLocation.longitude = -86628610;
|
|
cs0->chargingStationLocation.altitude.altitudeValue = epv.space.data.altitude.value;
|
|
cs0->chargingStationLocation.altitude.altitudeConfidence = epv.space.data.altitude.confidence;
|
|
cs0->chargingStationLocation.positionConfidenceEllipse.semiMajorConfidence = EI1_SemiAxisLength_unavailable;
|
|
cs0->chargingStationLocation.positionConfidenceEllipse.semiMinorConfidence = EI1_SemiAxisLength_unavailable;
|
|
cs0->chargingStationLocation.positionConfidenceEllipse.semiMajorOrientation = EI1_HeadingValue_unavailable;
|
|
cs0->accessibility = *create_utf8_from_string("Free Access", strlen("Free Access"));
|
|
cs0->pricing = *create_utf8_from_string(".15 €/kWh", strlen(".15 €/kWh"));
|
|
cs0->openingDaysHours = *create_utf8_from_string("Always", strlen("Always"));
|
|
const char *booking_url = "ccam.av.it.pt";
|
|
cs0->bookingContactInfo = create_utf8_from_string(booking_url, strlen(booking_url));
|
|
cs0->chargingSpotsAvailable.list.array = calloc(1, sizeof(void *));
|
|
cs0->chargingSpotsAvailable.list.count = 1;
|
|
cs0->chargingSpotsAvailable.list.size = sizeof(void *) * 1;
|
|
cs0->chargingSpotsAvailable.list.array[0] = calloc(1, sizeof(struct EI1_ItsChargingSpotDataElements));
|
|
struct EI1_ItsChargingSpotDataElements *cs_elem0 = cs0->chargingSpotsAvailable.list.array[0];
|
|
cs_elem0->energyAvailability = *create_utf8_from_string("Max: 30kW", strlen("Max: 30kW"));
|
|
cs_elem0->type.buf = calloc(1, sizeof(uint8_t));
|
|
cs_elem0->type.size = 1;
|
|
cs_elem0->type.bits_unused = 0;
|
|
cs_elem0->type.buf[0] = 0x03;
|
|
cs_elem0->typeOfReceptacle.buf = calloc(1, sizeof(uint8_t));
|
|
cs_elem0->typeOfReceptacle.size = 1;
|
|
cs_elem0->typeOfReceptacle.bits_unused = 0;
|
|
cs_elem0->typeOfReceptacle.buf[0] = 0x0D;
|
|
cs_elem0->parkingPlacesData = calloc(1, sizeof(struct EI1_ParkingPlacesData));
|
|
cs_elem0->parkingPlacesData->list.array = calloc(2, sizeof(void *));
|
|
cs_elem0->parkingPlacesData->list.count = 2;
|
|
cs_elem0->parkingPlacesData->list.size = sizeof(void *) * 2;
|
|
// As requested onnly 2 parking places are available
|
|
for (int parckingPlaceIndex = 0; parckingPlaceIndex < 2; parckingPlaceIndex++) {
|
|
cs_elem0->parkingPlacesData->list.array[parckingPlaceIndex] = calloc(1, sizeof(struct EI1_SpotAvailability));
|
|
struct EI1_SpotAvailability *spot = cs_elem0->parkingPlacesData->list.array[parckingPlaceIndex];
|
|
spot->maxWaitingTimeMinutes = 0;
|
|
spot->blocking = 1;
|
|
}
|
|
itss_space_unlock(epv);
|
|
// if (facilities.station_type == StationType_roadSideUnit)
|
|
//{
|
|
// }
|
|
|
|
asn_enc_rval_t enc = uper_encode_to_buffer(&asn_DEF_EI1_EvcsnPdu, NULL, evcsnm, evcsnm_oer, 512);
|
|
if (enc.encoded == -1) {
|
|
log_error("[ev] failed encoding evcsnm (%s)", enc.failed_type->name);
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
*evcsnm_len = (enc.encoded + 7) / 8;
|
|
|
|
cleanup:
|
|
ASN_STRUCT_FREE(asn_DEF_EI1_EvcsnPdu, evcsnm);
|
|
return rv;
|
|
}
|
|
|
|
static uint64_t pre_reservation_id = 1;
|
|
static uint64_t reservation_id = 1;
|
|
|
|
int evrsrm_recv(EI1_EV_RSR_t *evrsr_request) {
|
|
int rv = 0;
|
|
|
|
EIS_NetworkingRequest_t* nr = calloc(1, sizeof(EIS_NetworkingRequest_t));
|
|
nr->present = EIS_NetworkingRequest_PR_packet;
|
|
EIS_NetworkingPacketRequest_t* npr = &nr->choice.packet;
|
|
|
|
npr->network.present = EIS_NetworkingPacketRequestNW_PR_gn;
|
|
npr->network.choice.gn.trafficClass = 2;
|
|
npr->network.choice.gn.destinationAddress.buf = malloc(6);
|
|
for (int i = 0; i < 6; ++i) {
|
|
npr->network.choice.gn.destinationAddress.buf[i] = 0xff;
|
|
}
|
|
npr->network.choice.gn.destinationAddress.size = 6;
|
|
npr->network.choice.gn.packetTransportType = EIS_PacketTransportType_shb;
|
|
npr->network.choice.gn.securityProfile.sign = true;
|
|
|
|
npr->transport.present = EIS_NetworkingPacketRequestTP_PR_btp;
|
|
npr->transport.choice.btp.btpType = EIS_BTPType_btpB;
|
|
npr->transport.choice.btp.destinationPort = EIS_Port_evrsr;
|
|
|
|
npr->data.buf = malloc(512);
|
|
|
|
// Fill header for FacilitiesIndication and FacilitiesMessageIndication structs
|
|
|
|
|
|
EIS_FacilitiesIndication_t *fi = calloc(1, sizeof(EIS_FacilitiesIndication_t));
|
|
fi->present = EIS_FacilitiesIndication_PR_message;
|
|
EIS_FacilitiesMessageIndication_t *fmi = &fi->choice.message;
|
|
fmi->itsMessageType = EIS_ItsMessageType_evrsr;
|
|
fmi->data.buf = malloc(512);
|
|
|
|
uint8_t tr_oer[1024];
|
|
uint8_t fi_oer[1024];
|
|
tr_oer[0] = 4; // Facilities
|
|
fi_oer[0] = 4;
|
|
if (!(evrsr_request->messageBody.present == EI1_EV_RSR_MessageBody_PR_preReservationRequestMessage ||
|
|
evrsr_request->messageBody.present == EI1_EV_RSR_MessageBody_PR_reservationRequestMessage ||
|
|
evrsr_request->messageBody.present == EI1_EV_RSR_MessageBody_PR_cancellationRequestMessage ||
|
|
evrsr_request->messageBody.present == EI1_EV_RSR_MessageBody_PR_updateRequestMessage)) {
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
int evrsr_response;
|
|
if (evrsr_request->messageBody.present == EI1_EV_RSR_MessageBody_PR_preReservationRequestMessage)
|
|
evrsr_response = evrsrm_pre_reservation_response(npr->data.buf, (uint32_t *)&npr->data.size);
|
|
else if (evrsr_request->messageBody.present == EI1_EV_RSR_MessageBody_PR_reservationRequestMessage)
|
|
evrsr_response = evrsrm_reservation_response(evrsr_request, npr->data.buf, (uint32_t *)&npr->data.size);
|
|
else if (evrsr_request->messageBody.present == EI1_EV_RSR_MessageBody_PR_cancellationRequestMessage)
|
|
evrsr_response = evrsrm_cancellation_response(evrsr_request, npr->data.buf, (uint32_t *)&npr->data.size);
|
|
else if (evrsr_request->messageBody.present == EI1_EV_RSR_MessageBody_PR_updateRequestMessage)
|
|
evrsr_response = evrsrm_update_response(evrsr_request, npr->data.buf, (uint32_t *)&npr->data.size);
|
|
if (evrsr_response != 0) {
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
memcpy(fmi->data.buf, npr->data.buf, npr->data.size);
|
|
fmi->data.size = npr->data.size;
|
|
|
|
uint32_t id = itss_id(npr->data.buf, npr->data.size);
|
|
npr->id = id;
|
|
fmi->id = id;
|
|
|
|
asn_enc_rval_t enc = oer_encode_to_buffer(&asn_DEF_EIS_NetworkingRequest, NULL, nr, tr_oer + 1, 1023);
|
|
if (enc.encoded == -1) {
|
|
log_error("[ev] failed encoding transport request (%s)", enc.failed_type->name);
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
|
|
asn_enc_rval_t enc_fdi = oer_encode_to_buffer(&asn_DEF_EIS_FacilitiesIndication, NULL, fi, fi_oer + 1, 1023);
|
|
if (enc_fdi.encoded == -1) {
|
|
log_error("[ev] encoding FI for evrsrm failed");
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
itss_queue_send(facilities.tx_queue, tr_oer, enc.encoded + 1, ITSS_NETWORKING, id, "NR.packet.btp");
|
|
|
|
itss_queue_send(facilities.tx_queue, fi_oer, enc_fdi.encoded + 1, ITSS_APPLICATIONS, id, "FI.message");
|
|
|
|
cleanup:
|
|
log_debug("[ev] evrsrm_recv done with rv %d", rv);
|
|
return rv;
|
|
}
|
|
|
|
static int evrsrm_cancellation_response(EI1_EV_RSR_t *evrsrm_request, uint8_t *evrsrm_oer, uint32_t *evrsrm_len){
|
|
int rv = 0;
|
|
EI1_EV_RSR_t *evrsr_response = calloc(1, sizeof(EI1_EV_RSR_t));
|
|
evrsr_response->header.protocolVersion = 1;
|
|
evrsr_response->header.messageID = 7;
|
|
pthread_mutex_lock(&facilities.id.lock);
|
|
evrsr_response->header.stationID = facilities.id.station_id;
|
|
pthread_mutex_unlock(&facilities.id.lock);
|
|
evrsr_response->messageBody.present = EI1_EV_RSR_MessageBody_PR_cancellationResponseMessage;
|
|
EI1_CancellationResponseMessage_t *evrsr_cancellation_response = &evrsr_response->messageBody.choice.cancellationResponseMessage;
|
|
|
|
evrsr_cancellation_response->reservation_ID.buf = calloc(8, sizeof(uint8_t));
|
|
evrsr_cancellation_response->reservation_ID.size = 8;
|
|
memccpy(evrsr_cancellation_response->reservation_ID.buf, evrsrm_request->messageBody.choice.cancellationRequestMessage.reservation_ID.buf, 0, 8);
|
|
evrsr_cancellation_response->cancellationResponseCode = EI1_CancellationResponseCode_ok;
|
|
|
|
asn_enc_rval_t enc = uper_encode_to_buffer(&asn_DEF_EI1_EV_RSR, NULL, evrsr_response, evrsrm_oer, 512);
|
|
if (enc.encoded == -1) {
|
|
log_error("[ev] failed encoding evrsrm cancellation response (%s)", enc.failed_type->name);
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
*evrsrm_len = (enc.encoded + 7) / 8;
|
|
cleanup:
|
|
ASN_STRUCT_FREE(asn_DEF_EI1_EV_RSR, evrsr_response);
|
|
return rv;
|
|
}
|
|
static int evrsrm_update_response(EI1_EV_RSR_t *evrsrm_request, uint8_t *evrsrm_oer, uint32_t *evrsrm_len){
|
|
int rv = 0;
|
|
EI1_EV_RSR_t *evrsr_response = calloc(1, sizeof(EI1_EV_RSR_t));
|
|
evrsr_response->header.protocolVersion = 1;
|
|
evrsr_response->header.messageID = 7;
|
|
pthread_mutex_lock(&facilities.id.lock);
|
|
evrsr_response->header.stationID = facilities.id.station_id;
|
|
pthread_mutex_unlock(&facilities.id.lock);
|
|
|
|
evrsr_response->messageBody.present = EI1_EV_RSR_MessageBody_PR_updateResponseMessage;
|
|
EI1_UpdateResponseMessage_t *evrsr_update_response = &evrsr_response->messageBody.choice.updateResponseMessage;
|
|
|
|
evrsr_update_response->reservation_ID.buf = calloc(8, sizeof(uint8_t));
|
|
evrsr_update_response->reservation_ID.size = 8;
|
|
memccpy(evrsr_update_response->reservation_ID.buf, evrsrm_request->messageBody.choice.updateRequestMessage.reservation_ID.buf, 0, 8);
|
|
evrsr_update_response->updateResponseCode = EI1_UpdateResponseCode_ok;
|
|
|
|
asn_enc_rval_t enc = uper_encode_to_buffer(&asn_DEF_EI1_EV_RSR, NULL, evrsr_response, evrsrm_oer, 512);
|
|
if (enc.encoded == -1) {
|
|
log_error("[ev] failed encoding evrsrm update response (%s)", enc.failed_type->name);
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
*evrsrm_len = (enc.encoded + 7) / 8;
|
|
cleanup:
|
|
ASN_STRUCT_FREE(asn_DEF_EI1_EV_RSR, evrsr_response);
|
|
return rv;
|
|
}
|
|
|
|
|
|
static int evrsrm_reservation_response(EI1_EV_RSR_t *evrsrm_request, uint8_t *evrsrm_oer, uint32_t *evrsrm_len) {
|
|
int rv = 0;
|
|
EI1_EV_RSR_t *evrsr_response = calloc(1, sizeof(EI1_EV_RSR_t));
|
|
evrsr_response->header.protocolVersion = 1;
|
|
evrsr_response->header.messageID = 7;
|
|
pthread_mutex_lock(&facilities.id.lock);
|
|
evrsr_response->header.stationID = facilities.id.station_id;
|
|
pthread_mutex_unlock(&facilities.id.lock);
|
|
evrsr_response->messageBody.present = EI1_EV_RSR_MessageBody_PR_reservationResponseMessage;
|
|
|
|
EI1_ReservationResponseMessage_t *response = &evrsr_response->messageBody.choice.reservationResponseMessage;
|
|
// Assumes the pre reservation was successful
|
|
response->reservationResponseCode = EI1_ReservationResponseCode_ok;
|
|
|
|
response->reservation_ID = calloc(1, sizeof(EI1_Reservation_ID_t));
|
|
response->reservation_ID->buf = calloc(8, sizeof(uint8_t));
|
|
response->reservation_ID->size = 8;
|
|
response->reservation_ID->buf[0] = '0' + reservation_id / 10000000;
|
|
response->reservation_ID->buf[1] = '0' + (reservation_id / 1000000) % 10;
|
|
response->reservation_ID->buf[2] = '0' + (reservation_id / 100000) % 10;
|
|
response->reservation_ID->buf[3] = '0' + (reservation_id / 10000) % 10;
|
|
response->reservation_ID->buf[4] = '0' + (reservation_id / 1000) % 10;
|
|
response->reservation_ID->buf[5] = '0' + (reservation_id / 100) % 10;
|
|
response->reservation_ID->buf[6] = '0' + (reservation_id / 10) % 10;
|
|
response->reservation_ID->buf[7] = '0' + reservation_id % 10;
|
|
|
|
response->reservation_Password = calloc(1, sizeof(EI1_Reservation_Password_t));
|
|
response->reservation_Password->buf = calloc(8, sizeof(uint8_t));
|
|
response->reservation_Password->size = 8;
|
|
response->reservation_Password->buf[0] = 'i';
|
|
response->reservation_Password->buf[1] = 't';
|
|
response->reservation_Password->buf[2] = '2';
|
|
response->reservation_Password->buf[3] = 's';
|
|
response->reservation_Password->buf[4] = 'i';
|
|
response->reservation_Password->buf[5] = 't';
|
|
response->reservation_Password->buf[6] = '2';
|
|
response->reservation_Password->buf[7] = 's';
|
|
// estimated arrival time + tolerance time
|
|
response->expirationTime = evrsrm_request->messageBody.choice.reservationRequestMessage.arrivalTime;
|
|
response->expirationTime += 15 * 60 * 1000; // 15 minutes
|
|
|
|
asn_enc_rval_t enc = uper_encode_to_buffer(&asn_DEF_EI1_EV_RSR, NULL, evrsr_response, evrsrm_oer, 512);
|
|
if (enc.encoded == -1) {
|
|
log_error("[ev] failed encoding evrsrm reservation response (%s)", enc.failed_type->name);
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
*evrsrm_len = (enc.encoded + 7) / 8;
|
|
reservation_id++;
|
|
|
|
cleanup:
|
|
ASN_STRUCT_FREE(asn_DEF_EI1_EV_RSR, evrsr_response);
|
|
return rv;
|
|
}
|
|
static int evrsrm_pre_reservation_response(uint8_t *evrsrm_oer, uint32_t *evrsrm_len) {
|
|
int rv = 0;
|
|
EI1_EV_RSR_t *evrsr_response = calloc(1, sizeof(EI1_EV_RSR_t));
|
|
evrsr_response->header.protocolVersion = 1;
|
|
evrsr_response->header.messageID = 7;
|
|
pthread_mutex_lock(&facilities.id.lock);
|
|
evrsr_response->header.stationID = facilities.id.station_id;
|
|
pthread_mutex_unlock(&facilities.id.lock);
|
|
evrsr_response->messageBody.present = EI1_EV_RSR_MessageBody_PR_preReservationResponseMessage;
|
|
|
|
EI1_PreReservationResponseMessage_t *response = &evrsr_response->messageBody.choice.preReservationResponseMessage;
|
|
response->preReservation_ID.buf = calloc(8, sizeof(uint8_t));
|
|
response->preReservation_ID.size = 8;
|
|
response->preReservation_ID.buf[0] = '0' + (pre_reservation_id / 10000000);
|
|
response->preReservation_ID.buf[1] = '0' + (pre_reservation_id / 1000000) % 10;
|
|
response->preReservation_ID.buf[2] = '0' + (pre_reservation_id / 100000) % 10;
|
|
response->preReservation_ID.buf[3] = '0' + (pre_reservation_id / 10000) % 10;
|
|
response->preReservation_ID.buf[4] = '0' + (pre_reservation_id / 1000) % 10;
|
|
response->preReservation_ID.buf[5] = '0' + (pre_reservation_id / 100) % 10;
|
|
response->preReservation_ID.buf[6] = '0' + (pre_reservation_id / 10) % 10;
|
|
response->preReservation_ID.buf[7] = '0' + pre_reservation_id % 10;
|
|
|
|
response->availabilityStatus = 0;
|
|
|
|
response->supportedPaymentTypes.buf = calloc(1, sizeof(uint8_t));
|
|
response->supportedPaymentTypes.bits_unused = 0;
|
|
response->supportedPaymentTypes.size = 1;
|
|
response->supportedPaymentTypes.buf[0] = 0x00;
|
|
|
|
response->preReservationExpirationTime = 0;
|
|
asn_enc_rval_t enc = uper_encode_to_buffer(&asn_DEF_EI1_EV_RSR, NULL, evrsr_response, evrsrm_oer, 512);
|
|
if (enc.encoded == -1) {
|
|
log_error("[ev] failed encoding evrsrm pre reservation response (%s)", enc.failed_type->name);
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
*evrsrm_len = (enc.encoded + 7) / 8;
|
|
pre_reservation_id++;
|
|
|
|
cleanup:
|
|
ASN_STRUCT_FREE(asn_DEF_EI1_EV_RSR, evrsr_response);
|
|
return rv;
|
|
}
|
|
|
|
int evcsnm_check(EI1_EvcsnPdu_t *evcsnm) {
|
|
return 0;
|
|
}
|
|
|
|
int evrsrm_check(EI1_EV_RSR_t *evrsrm) {
|
|
return 0;
|
|
}
|
|
|
|
enum EVM_CHECK_R check_evcsnm(EIS_BTPPacketIndication_t *bpi, EI1_EvcsnPdu_t *evcsnm, uint8_t *ssp, uint32_t ssp_len) {
|
|
return 0;
|
|
}
|
|
|
|
enum EVM_CHECK_R check_evrsrm(EIS_BTPPacketIndication_t *bpi, EI1_EV_RSR_t *evrsrm, uint8_t *ssp, uint32_t ssp_len) {
|
|
return 0;
|
|
}
|
|
|
|
void *evcsn_service() {
|
|
int rv = 0;
|
|
|
|
EIS_NetworkingRequest_t* nr = calloc(1, sizeof(EIS_NetworkingRequest_t));
|
|
nr->present = EIS_NetworkingRequest_PR_packet;
|
|
EIS_NetworkingPacketRequest_t* npr = &nr->choice.packet;
|
|
|
|
npr->network.present = EIS_NetworkingPacketRequestNW_PR_gn;
|
|
npr->network.choice.gn.trafficClass = 2;
|
|
npr->network.choice.gn.destinationAddress.buf = malloc(6);
|
|
for (int i = 0; i < 6; ++i) {
|
|
npr->network.choice.gn.destinationAddress.buf[i] = 0xff;
|
|
}
|
|
npr->network.choice.gn.destinationAddress.size = 6;
|
|
npr->network.choice.gn.packetTransportType = EIS_PacketTransportType_shb;
|
|
npr->network.choice.gn.securityProfile.sign = true;
|
|
|
|
npr->transport.present = EIS_NetworkingPacketRequestTP_PR_btp;
|
|
npr->transport.choice.btp.btpType = EIS_BTPType_btpB;
|
|
npr->transport.choice.btp.destinationPort = EIS_Port_poi;
|
|
|
|
|
|
npr->data.buf = malloc(512);
|
|
|
|
// Fill header for FacilitiesIndication and FacilitiesMessageIndication structs
|
|
|
|
EIS_FacilitiesIndication_t *fi = calloc(1, sizeof(EIS_FacilitiesIndication_t));
|
|
fi->present = EIS_FacilitiesIndication_PR_message;
|
|
EIS_FacilitiesMessageIndication_t *fmi = &fi->choice.message;
|
|
fmi->itsMessageType = EIS_ItsMessageType_poi;
|
|
fmi->data.buf = malloc(512);
|
|
|
|
uint8_t tr_oer[1024];
|
|
uint8_t fi_oer[1024];
|
|
tr_oer[0] = 4; // Facilities
|
|
fi_oer[0] = 4;
|
|
while (!facilities.exit) {
|
|
itss_usleep(1000 * 1000);
|
|
if (facilities.evm_args.activate) {
|
|
rv = mk_evcsnm(npr->data.buf, (uint32_t *)&npr->data.size);
|
|
if (rv) {
|
|
continue;
|
|
}
|
|
memcpy(fmi->data.buf, npr->data.buf, npr->data.size);
|
|
fmi->data.size = npr->data.size;
|
|
|
|
uint32_t id = itss_id(npr->data.buf, npr->data.size);
|
|
npr->id = id;
|
|
fmi->id = id;
|
|
|
|
asn_enc_rval_t enc = oer_encode_to_buffer(&asn_DEF_EIS_NetworkingRequest, NULL, nr, tr_oer + 1, 1023);
|
|
if (enc.encoded == -1) {
|
|
log_error("encoding TR for evcsnm failed");
|
|
continue;
|
|
}
|
|
|
|
asn_enc_rval_t enc_fdi = oer_encode_to_buffer(&asn_DEF_EIS_FacilitiesIndication, NULL, fi, fi_oer + 1, 1023);
|
|
if (enc_fdi.encoded == -1) {
|
|
log_error("encoding FI for evcsnm failed");
|
|
continue;
|
|
}
|
|
|
|
itss_queue_send(facilities.tx_queue, tr_oer, enc.encoded + 1, ITSS_NETWORKING, id, "NR.packet.btp");
|
|
|
|
itss_queue_send(facilities.tx_queue, fi_oer, enc_fdi.encoded + 1, ITSS_APPLICATIONS, id, "FI.message");
|
|
|
|
// Logging
|
|
if (facilities.logging.dbms) {
|
|
pthread_mutex_lock(&facilities.id.lock);
|
|
uint32_t station_id = facilities.id.station_id;
|
|
pthread_mutex_unlock(&facilities.id.lock);
|
|
itss_db_add(facilities.logging.dbms, station_id, npr->id, true, EI1_messageID_evcsn, NULL, npr->data.buf, npr->data.size);
|
|
}
|
|
|
|
if (facilities.logging.recorder) {
|
|
uint16_t buffer_len = 2048;
|
|
uint8_t buffer[buffer_len];
|
|
int e = itss_management_record_packet_sdu(
|
|
buffer,
|
|
buffer_len,
|
|
npr->data.buf,
|
|
npr->data.size,
|
|
id,
|
|
itss_time_get(),
|
|
ITSS_FACILITIES,
|
|
true);
|
|
if (e != -1) {
|
|
itss_queue_send(facilities.tx_queue, buffer, e, ITSS_MANAGEMENT, id, "MReq.packet.set");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ASN_STRUCT_FREE(asn_DEF_EIS_NetworkingRequest, nr);
|
|
|
|
return NULL;
|
|
}
|