#include "evcsnm.h" #include "facilities.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); }