it2s-itss-facilities/src/evcsnm.c

248 lines
8.9 KiB
C

#include "evcsnm.h"
#include "facilities.h"
#include <it2s-asn/itss-transport/TransportRequest.h>
#include <it2s-asn/itss-facilities/FacilitiesIndication.h>
#include <it2s-asn/itss-management/ManagementRequest.h>
#include <it2s-asn/evcsnm/EvcsnPdu.h>
#include <sys/mman.h>
#include <stdint.h>
#include <time.h>
#include <zmq.h>
#include <unistd.h>
#include <math.h>
#include <fcntl.h>
#include <it2s-tender/space.h>
#include <it2s-tender/time.h>
#include <it2s-tender/database.h>
#include <it2s-tender/constants.h>
#include <it2s-tender/recorder.h>
#include <it2s-tender/packet.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 + 1, sizeof(uint8_t));
utf8_string->size = length + 1;
memcpy(utf8_string->buf, string, length);
utf8_string->buf[length] = '\0';
return utf8_string;
}
static UTF8String_t *create_empty_utf8_string()
{
UTF8String_t *utf8_string = calloc(1, sizeof(UTF8String_t));
utf8_string->buf = calloc(1, 1);
utf8_string->size = 1;
utf8_string->buf[0] = '\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;
EvcsnPdu_t *evcsnm = calloc(1, sizeof(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();
evcsnm->evcsn.poiHeader.poiType = 1; // set to "EV charging station POI ID = 1"
asn_ulong2INTEGER(&evcsnm->evcsn.poiHeader.timeStamp, now);
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 ItsChargingStationData));
struct 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.altitude;
cs0->chargingStationLocation.altitude.altitudeConfidence = epv.space.altitude_conf;
cs0->chargingStationLocation.positionConfidenceEllipse.semiMajorConfidence = SemiAxisLength_unavailable;
cs0->chargingStationLocation.positionConfidenceEllipse.semiMinorConfidence = SemiAxisLength_unavailable;
cs0->chargingStationLocation.positionConfidenceEllipse.semiMajorOrientation = HeadingValue_unavailable;
cs0->accessibility = *create_empty_utf8_string();
cs0->pricing = *create_empty_utf8_string();
cs0->openingDaysHours = *create_empty_utf8_string();
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 ItsChargingSpotDataElements));
struct ItsChargingSpotDataElements *cs_elem0 = cs0->chargingSpotsAvailable.list.array[0];
cs_elem0->energyAvailability = *create_empty_utf8_string();
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 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 SpotAvailability));
struct 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_EvcsnPdu, NULL, evcsnm, evcsnm_oer, 512);
if (enc.encoded == -1)
{
log_error("[ca] failed encoding evcsnm (%s)", enc.failed_type->name);
rv = 1;
goto cleanup;
}
*evcsnm_len = (enc.encoded + 7) / 8;
cleanup:
ASN_STRUCT_FREE(asn_DEF_EvcsnPdu, evcsnm);
return rv;
}
int evcsnm_check(EvcsnPdu_t *evcsnm)
{
return 0;
}
enum EVCSNM_CHECK_R check_evcsnm(BTPPacketIndication_t *bpi, EvcsnPdu_t *evcsnm, uint8_t *ssp, uint32_t ssp_len)
{
int rv = 0;
return rv;
}
void *evcsn_service()
{
int rv = 0;
TransportRequest_t *tr = calloc(1, sizeof(TransportRequest_t));
tr->present = TransportRequest_PR_packet;
TransportPacketRequest_t *tpr = &tr->choice.packet;
tpr->present = TransportPacketRequest_PR_btp;
BTPPacketRequest_t *bpr = &tpr->choice.btp;
bpr->btpType = BTPType_btpB;
bpr->gn.destinationAddress.buf = malloc(6);
for (int i = 0; i < 6; ++i)
{
bpr->gn.destinationAddress.buf[i] = 0xff;
}
bpr->gn.destinationAddress.size = 6;
bpr->gn.packetTransportType = PacketTransportType_shb;
bpr->destinationPort = Port_poi;
bpr->gn.trafficClass = 2;
bpr->data.buf = malloc(512);
// Fill header for FacilitiesIndication and FacilitiesMessageIndication structs
bpr->gn.securityProfile.sign = true;
FacilitiesIndication_t *fi = calloc(1, sizeof(FacilitiesIndication_t));
fi->present = FacilitiesIndication_PR_message;
FacilitiesMessageIndication_t *fmi = &fi->choice.message;
fmi->itsMessageType = 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)
{
usleep(1000 * 1000);
if (facilities.evcsnm_args.activate)
{
rv = mk_evcsnm(bpr->data.buf, (uint32_t *)&bpr->data.size);
if (rv)
{
continue;
}
memcpy(fmi->data.buf, bpr->data.buf, bpr->data.size);
fmi->data.size = bpr->data.size;
uint32_t id = itss_id(bpr->data.buf, bpr->data.size);
bpr->id = id;
fmi->id = id;
asn_enc_rval_t enc = oer_encode_to_buffer(&asn_DEF_TransportRequest, NULL, tr, 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_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_TRANSPORT, id, "TR.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, bpr->id, true, messageID_evcsn, NULL, bpr->data.buf, bpr->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,
bpr->data.buf,
bpr->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_TransportRequest, tr);
return NULL;
}