func encodeAndEnqueueReportingInterval(mins uint32) error { if downlinkMessages != nil { // Create a buffer that is big enough to store all // the encoded data and take a pointer to it's first element var outputBuffer [C.MAX_DATAGRAM_SIZE_RAW]byte outputPointer := (*C.char)(unsafe.Pointer(&outputBuffer[0])) // Populate the data struture to be encoded var data C.ReportingIntervalSetReqDlMsg_t // data.reportingIntervalMinutes = C.uint32_t(mins) var dataPointer = (*C.ReportingIntervalSetReqDlMsg_t)(unsafe.Pointer(&data)) // Encode the data structure into the output buffer cbytes := C.encodeReportingIntervalSetReqDlMsg(outputPointer, dataPointer, nil, nil) // Send the populated output buffer bytes to NeulNet payload := outputBuffer[:cbytes] msg := AmqpMessage{ Device_uuid: ueGuid, Endpoint_uuid: 4, //Payload: payload, } for _, v := range payload { msg.Payload = append(msg.Payload, int(v)) Row.TotalBytes = Row.TotalBytes + uint64(len(payload)) } log.Printf("%s ENCODED A REPORTING INTERVAL UPDATE OF %d MINUTES AS %v USING AMQP MESSAGE %+v\n", logTag, mins, payload, msg) downlinkMessages <- msg now := time.Now() // Record the downlink data volume StateTableCmds <- &DataVolume{ DownlinkTimestamp: &now, DownlinkBytes: uint64(len(payload)), } return nil } return errors.New("NO DOWNLINKMESSAGES CHANNEL AVAILABLE TO ENQUEUE THE ENCODED MESSAGE") }
// Encode and enqueue a message, return an error if there is one func encodeAndEnqueue(msg interface{}, uuid string) error { if msg != nil { // Create a buffer that is big enough to store all // the encoded data and take a pointer to it's first element var outputBuffer [MaxDatagramSizeRaw]byte outputPointer := (*C.char)(unsafe.Pointer(&outputBuffer[0])) var byteCount C.uint32_t = 0 responseId := RESPONSE_NONE // A place to put the XML output from the decoder pXmlBuffer := (*C.char)(unsafe.Pointer(&(xmlEncodeBuffer[0]))) ppXmlBuffer := (**C.char)(unsafe.Pointer(&pXmlBuffer)) xmlBufferLen := (C.uint32_t)(len(xmlEncodeBuffer)) pXmlBufferLen := (*C.uint32_t)(unsafe.Pointer(&xmlBufferLen)) // Encode each message type switch value := msg.(type) { case *TransparentDlDatagram: // TODO case *PingReqDlMsg: byteCount = C.encodePingReqMsg(outputPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded PingReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_PING_CNF case *PingCnfDlMsg: byteCount = C.encodePingCnfMsg(outputPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded PingCnfDlMsg.\n", globals.LogTag) case *RebootReqDlMsg: data := C.RebootReqDlMsg_t{ sdCardNotRequired: (C.bool)(value.SdCardNotRequired), disableModemDebug: (C.bool)(value.DisableModemDebug), disableButton: (C.bool)(value.DisableButton), disableServerPing: (C.bool)(value.DisableServerPing), } dataPointer := (*C.RebootReqDlMsg_t)(unsafe.Pointer(&data)) byteCount = C.encodeRebootReqDlMsg(outputPointer, dataPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded RebootReqDlMsg.\n", globals.LogTag) case *DateTimeSetReqDlMsg: data := C.DateTimeSetReqDlMsg_t{ time: (C.uint32_t)(value.UtmTime.Unix()), setDateOnly: (C.bool)(value.SetDateOnly), } dataPointer := (*C.DateTimeSetReqDlMsg_t)(unsafe.Pointer(&data)) byteCount = C.encodeDateTimeSetReqDlMsg(outputPointer, dataPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded DateTimeSetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_DATE_TIME_SET_CNF case *DateTimeGetReqDlMsg: byteCount = C.encodeDateTimeGetReqDlMsg(outputPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded DateTimeGetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_DATE_TIME_GET_CNF case *ModeSetReqDlMsg: data := C.ModeSetReqDlMsg_t{ mode: (C.Mode_t)(value.Mode), } dataPointer := (*C.ModeSetReqDlMsg_t)(unsafe.Pointer(&data)) byteCount = C.encodeModeSetReqDlMsg(outputPointer, dataPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded ModeSetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_MODE_SET_CNF case *ModeGetReqDlMsg: byteCount = C.encodeModeGetReqDlMsg(outputPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded ModeGetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_MODE_GET_CNF case *IntervalsGetReqDlMsg: byteCount = C.encodeIntervalsGetReqDlMsg(outputPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded IntervalsGetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_INTERVALS_GET_CNF case *ReportingIntervalSetReqDlMsg: data := C.ReportingIntervalSetReqDlMsg_t{ reportingInterval: (C.uint32_t)(value.ReportingInterval), } dataPointer := (*C.ReportingIntervalSetReqDlMsg_t)(unsafe.Pointer(&data)) byteCount = C.encodeReportingIntervalSetReqDlMsg(outputPointer, dataPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded ReportingIntervalSetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_REPORTING_INTERVAL_SET_CNF case *HeartbeatSetReqDlMsg: data := C.HeartbeatSetReqDlMsg_t{ heartbeatSeconds: (C.uint32_t)(value.HeartbeatSeconds), heartbeatSnapToRtc: (C.bool)(value.HeartbeatSnapToRtc), } dataPointer := (*C.HeartbeatSetReqDlMsg_t)(unsafe.Pointer(&data)) byteCount = C.encodeHeartbeatSetReqDlMsg(outputPointer, dataPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded HeartbeatSetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_HEARTBEAT_SET_CNF case *MeasurementsGetReqDlMsg: byteCount = C.encodeMeasurementsGetReqDlMsg(outputPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded MeasurementsReportReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_MEASUREMENTS_GET_CNF // TODO // case *MeasurementControlSetReqDlMsg // case *MeasurementsControlDefaultsSetReqDlMsg case *TrafficReportGetReqDlMsg: byteCount = C.encodeTrafficReportGetReqDlMsg(outputPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded TrafficReportGetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_TRAFFIC_REPORT_GET_CNF case *TrafficTestModeParametersSetReqDlMsg: data := C.TrafficTestModeParametersSetReqDlMsg_t{ numUlDatagrams: (C.uint32_t)(value.NumUlDatagrams), lenUlDatagram: (C.uint32_t)(value.LenUlDatagram), numDlDatagrams: (C.uint32_t)(value.NumDlDatagrams), lenDlDatagram: (C.uint32_t)(value.LenDlDatagram), timeoutSeconds: (C.uint32_t)(value.TimeoutSeconds), noReportsDuringTest: (C.bool)(value.NoReportsDuringTest), } dataPointer := (*C.TrafficTestModeParametersSetReqDlMsg_t)(unsafe.Pointer(&data)) byteCount = C.encodeTrafficTestModeParametersSetReqDlMsg(outputPointer, dataPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded TrafficTestModeParametersSetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_TRAFFIC_TEST_MODE_PARAMETERS_SET_CNF case *TrafficTestModeParametersGetReqDlMsg: byteCount = C.encodeTrafficTestModeParametersGetReqDlMsg(outputPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded TrafficTestModeParametersGetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_TRAFFIC_TEST_MODE_PARAMETERS_GET_CNF case *TrafficTestModeReportGetReqDlMsg: byteCount = C.encodeTrafficTestModeReportGetReqDlMsg(outputPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded TrafficTestModeReportGetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_TRAFFIC_TEST_MODE_REPORT_GET_CNF case *ActivityReportGetReqDlMsg: byteCount = C.encodeActivityReportGetReqDlMsg(outputPointer, ppXmlBuffer, pXmlBufferLen) globals.Dbg.PrintfTrace("%s [encode] --> encoded ActivityReportGetReqDlMsg.\n", globals.LogTag) responseId = RESPONSE_ACTIVITY_REPORT_GET_CNF default: globals.Dbg.PrintfTrace("%s [encode] --> asked to send unknown message:\n\n%s\n", globals.LogTag, spew.Sdump(msg)) } if byteCount > 0 { totalDlMsgs++ totalDlBytes += int(byteCount) lastDlMsgTime = time.Now() // Send the output buffer to the TSW server payload := outputBuffer[:byteCount] msg := AmqpMessage{ DeviceUuid: uuid, EndpointUuid: 4, } for _, v := range payload { msg.Payload = append(msg.Payload, int(v)) } globals.Dbg.PrintfTrace("%s [encode] --> %d byte message for AMQP downlink:\n\n%+v\n", globals.LogTag, byteCount, msg) downlinkMessages <- msg globals.Dbg.PrintfTrace("%s [encode] --> encoded %d bytes into AMQP message:\n\n%+v\n", globals.LogTag, byteCount, msg) globals.Dbg.PrintfInfo("%s [encode] --> XML buffer pointer 0x%08x, used %d, left %d:.\n", globals.LogTag, *ppXmlBuffer, C.uint32_t(len(xmlEncodeBuffer))-xmlBufferLen, xmlBufferLen) // If a response is expected, add it to the list for this device if responseId != RESPONSE_NONE { globals.Dbg.PrintfTrace("%s [encode] --> now expecting response ID %d from UUID %s.\n", globals.LogTag, responseId, uuid) list := deviceExpectedMsgList[uuid] if list == nil { var expectedMsgList []ExpectedMsg list = &expectedMsgList deviceExpectedMsgList[uuid] = list globals.Dbg.PrintfTrace("%s [encode] --> making a new list for UUID %s, number of lists is now %d.\n", globals.LogTag, uuid, len(deviceExpectedMsgList)) } expectedMsg := ExpectedMsg{ TimeStarted: time.Now(), ResponseId: responseId, } *list = append(*list, expectedMsg) globals.Dbg.PrintfTrace("%s [encode] --> expected list for UUID %s is now size %d.\n", globals.LogTag, uuid, len(*list)) } return nil } return nil } return errors.New("No downlink message channel available to enqueue the encoded message.\n") }