238 lines
8.0 KiB
C
238 lines
8.0 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_empty_utf8_string()
|
|
{
|
|
UTF8String_t *utf8_string = calloc(1, sizeof(UTF8String_t));
|
|
utf8_string->buf = calloc(1, 1);
|
|
utf8_string->size = 1;
|
|
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 = 0;
|
|
|
|
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 = epv.space.latitude;
|
|
cs0->chargingStationLocation.longitude = epv.space.longitude;
|
|
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();
|
|
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] = 0xff;
|
|
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] = 0xff;
|
|
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;
|
|
}
|
|
|
|
|
|
evcs_info_t* evcs_info_new(EVCSInfo_t* tpi) {
|
|
evcs_info_t* ti = calloc(1, sizeof(evcs_info_t));
|
|
|
|
ti->timestamp = itss_time_get();
|
|
ti->asn = tpi;
|
|
|
|
return ti;
|
|
}
|
|
|
|
void evcs_info_free(evcs_info_t* ti) {
|
|
ASN_STRUCT_FREE(asn_DEF_EVCSInfo, ti->asn);
|
|
free(ti);
|
|
}
|