📄 geozone.c
字号:
static CommandError_t _geozAddGeoZone(GeoZone_t *gz){#ifdef GEOZ_INCL_PRINT_GEOZONE //_geozPrintGeoZone(gz);#endif /* valid zone ID? */ if (!IS_VALID_ZONE(gz->zoneID)) { // NO_ZONE // '0' is reserved for 'No GeoZone' return COMMAND_ZONE_ID; } /* validate radius */ if (gz->radius <= 0) { // the radius must be > 0 return COMMAND_RADIUS; } /* validate type */ GPSPoint_t pt0, pt1; _geozToGPSPoint(&pt0, &(gz->point[0])); _geozToGPSPoint(&pt1, &(gz->point[1]));#ifdef GEOF_DUAL_POINT_RADIUS // Two separate points with the same specified radius if (gz->type == GEOF_DUAL_POINT_RADIUS) { if (!gpsPointIsValid(&pt0)) { if (gpsPointIsValid(&pt1)) { // move the valid point into point[0] gz->point[0].latitude = gz->point[1].latitude; gz->point[0].longitude = gz->point[1].longitude; gz->point[1].latitude = 0.0; gz->point[1].longitude = 0.0; } else { // at least one point must be valid return COMMAND_LATLON; } } } else#endif#ifdef GEOF_BOUNDED_RECT // A simple rectangle bounded by an North-West point, and a South-East point if (gz->type == GEOF_BOUNDED_RECT) { // This GeoZone type will fail if the points spans the +/-180 deg meridian if (!gpsPointIsValid(&pt0) || !gpsPointIsValid(&pt1)) { // both points must be valid return COMMAND_LATLON; } if (gz->point[0].latitude < gz->point[1].latitude) { // move larger latitude to point[0] float tmp = gz->point[0].latitude; gz->point[0].latitude = gz->point[1].latitude; gz->point[1].latitude = tmp; } if (gz->point[0].longitude > gz->point[1].longitude) { // move smaller longitude to point[0] float tmp = gz->point[0].longitude; gz->point[0].longitude = gz->point[1].longitude; gz->point[1].longitude = tmp; } } else#endif#ifdef GEOF_SWEPT_POINT_RADIUS // A point radius swept over the globe from one point to another if (gz->type == GEOF_SWEPT_POINT_RADIUS) { if (!gpsPointIsValid(&pt0) || !gpsPointIsValid(&pt0)) { // both points must be valid return COMMAND_LATLON; } // The points should be a reasonable distance apart (ie. no more than a few miles) } else#endif#ifdef GEOF_DELTA_RECT // A center point with a +/- delta offset if (gz->type == GEOF_DELTA_RECT) { // This GeoZone type will fail if the points spans the +/-180 deg meridian if (!gpsPointIsValid(&pt0)) { // the center point must be valid return COMMAND_LATLON; } if (gz->point[1].latitude == 0.0) { // The delta latitude must be non zero //gz->point[1].latitude = 0.0200; return COMMAND_LATLON; } if (gz->point[1].longitude == 0.0) { // The delta latitude must be non zero //gz->point[1].longitude = 0.0200; return COMMAND_LATLON; } if (gz->point[1].latitude < 0.0) { // The delta latitude must be positive gz->point[1].latitude = -gz->point[1].latitude; } if (gz->point[1].longitude < 0.0) { // The delta latitude must be positive gz->point[1].longitude = -gz->point[1].longitude; } } else#endif { // type not supported return COMMAND_TYPE; } /* unique ZoneIDs? */#ifdef FORCE_UNIQUE_ZONE_IDS _geozRemoveGeoZone(gz->zoneID);#endif /* get available insert point */ UInt16 zoneNdx = 0; for (zoneNdx = 0; zoneNdx < usedZones; zoneNdx++) { if (!IS_VALID_ZONE(geoZoneList[zoneNdx].zoneID)) { // NO_ZONE break; } } if (zoneNdx >= maxZones) { // we've reached the maximum limit return COMMAND_OVERFLOW; } if (usedZones <= zoneNdx) { // we're allocating another unused zone usedZones = zoneNdx + 1; } /* add new geoZone */ memcpy(&geoZoneList[zoneNdx], gz, sizeof(GeoZone_t)); geozIsDirty = utTrue; return COMMAND_OK; }utBool geozAddGeoZone(GeoZone_t *gz){ if (gz) { utBool addErr = utFalse; GEOZ_LOCK { addErr = (_geozAddGeoZone(gz) == COMMAND_OK)? utTrue : utFalse; } GEOZ_UNLOCK return addErr; } else { return utFalse; }}// ----------------------------------------------------------------------------static utBool _geozRemoveGeoZone(GeoZoneID_t zoneID){ /* remove all GeoZones */ if (zoneID == NO_ZONE) { if (usedZones != 0) { usedZones = 0; geozIsDirty = utTrue; return utTrue; } else { return utFalse; } } /* remove all matching geoZones */ utBool rtn = utFalse; UInt16 i; for (i = 0; i < usedZones; i++) { if (zoneID == geoZoneList[i].zoneID) { geoZoneList[i].zoneID = NO_ZONE; geozIsDirty = utTrue; rtn = utTrue; } } /* trim back invalid zones at end of list */ for (; (usedZones > 0) && !IS_VALID_ZONE(geoZoneList[usedZones-1].zoneID); usedZones--); /* clear current zone, if this zone was deleted */ GeoZoneID_t curZoneID = geozGetCurrentID(); if (zoneID == curZoneID) { geozSetCurrentID(NO_ZONE); } return rtn;}utBool geozRemoveGeoZone(GeoZoneID_t zoneID){ utBool rmvErr = utFalse; GEOZ_LOCK { rmvErr = _geozRemoveGeoZone(zoneID); } GEOZ_UNLOCK return rmvErr;}// ----------------------------------------------------------------------------UInt16 geozGetGeoZoneCount(){ UInt16 i, count = 0; for (i = 0; i < usedZones; i++) { if (geoZoneList[i].zoneID != NO_ZONE) { count++; } } return count;}// ----------------------------------------------------------------------------static utBool _geozSaveGeoZones(const char *geozName){ /* invalid file name? */ if (!geozName || !*geozName) { return utFalse; } /* file name */ char geozFile[256]; sprintf(geozFile, "%s", geozName); /* open file for writing */ FILE *file = ioOpenStream(geozFile, IO_OPEN_WRITE); if (!file) { // error openning logERROR(LOGSRC,"Unable to open GeoZone file for writing: %s", geozFile); return utFalse; } /* write geozones to file */ UInt16 i = 0, count = 0; for (i = 0; i < usedZones; i++) { if (geoZoneList[i].zoneID != NO_ZONE) { long wrtLen = ioWriteStream(file, (UInt8*)&geoZoneList[i], sizeof(GeoZone_t)); if (wrtLen < sizeof(GeoZone_t)) { logERROR(LOGSRC,"Unable to write GeoZone: [%ld] %s", i, geozFile); ioCloseStream(file); return utFalse; } count++; } } /* close file */ logINFO(LOGSRC,"Saved GeoZone file: %s [%u]", geozFile, count); ioCloseStream(file); geozIsDirty = utFalse; return utTrue;}utBool geozSaveGeoZone(){ utBool savErr = utFalse; GEOZ_LOCK { savErr = _geozSaveGeoZones(GEOZONE_FILENAME); } GEOZ_UNLOCK return savErr;}// ----------------------------------------------------------------------------static utBool _geozLoadGeoZones(const char *geozName){ /* reset terminals */ _geozClearAll(); geozIsDirty = utFalse; /* file name */ char geozFile[256]; sprintf(geozFile, "%s", geozName); /* make sure file exists */ if (!ioIsFile(geozFile)) { logINFO(LOGSRC,"GeoZone file does not exist: %s", geozFile); return utFalse; } /* open file for writing */ FILE *file = ioOpenStream(geozFile, IO_OPEN_READ); if (!file) { // error openning logERROR(LOGSRC,"Unable to open GeoZone file for reading: %s", geozFile); return utFalse; } /* read terminals */ logINFO(LOGSRC,"Loading GeoZones: %s", geozFile); usedZones = 0; for (; usedZones < maxZones; usedZones++) { GeoZone_t *geoz = &geoZoneList[usedZones]; /* read GeoZone record */ long vlen = ioReadStream(file, geoz, sizeof(GeoZone_t)); if (vlen < 0L) { logERROR(LOGSRC,"Error reading GeoZone: [rcd=%u] %s", usedZones, geozFile); ioCloseStream(file); return utFalse; // error } else if (vlen == 0L) { logINFO(LOGSRC,"Loaded GeoZones: [cnt=%u] %s", usedZones, geozFile); ioCloseStream(file); break; } else if (vlen < sizeof(GeoZone_t)) { logERROR(LOGSRC,"Unable to read GeoZone: [rcd=%u] %s", usedZones, geozFile); ioCloseStream(file); return utFalse; // error }#ifdef GEOZ_INCL_PRINT_GEOZONE //_geozPrintGeoZone(geoz);#endif } return utTrue;}// ----------------------------------------------------------------------------// PROP_CMD_GEOF_ADMIN property handlerCommandError_t _cmdGeoZoneAdmin(int pi, Key_t key, const UInt8 *data, int dataLen){ /* init buffer */ Buffer_t bsrc, *src = binBuffer(&bsrc, (UInt8*)data, dataLen, BUFFER_SOURCE); if (BUFFER_DATA_LENGTH(src) < 1) { return COMMAND_ARGUMENTS; } /* admin command type */ Int32 adminType = -1L; binBufScanf(src, "%1u", &adminType); CommandError_t cmdErr = COMMAND_FEATURE_NOT_SUPPORTED; switch ((Int16)adminType) { case GEOF_CMD_ADD_STD: // Add GeoZone list to table (standard resolution) case GEOF_CMD_ADD_HIGH: // Add GeoZone list to table (high resolution) cmdErr = COMMAND_OK; GEOZ_LOCK { utBool hiRes = ((Int16)adminType == GEOF_CMD_ADD_HIGH)? utTrue : utFalse; while (BUFFER_DATA_LENGTH(src) >= PACKED_GEOZONE_SIZE) { GeoZone_t gz; if (_geozDecodeGeoZone(src, &gz, hiRes)) { CommandError_t addErr = _geozAddGeoZone(&gz); if (addErr != COMMAND_OK) { cmdErr = addErr; } } else { cmdErr = COMMAND_ARGUMENTS; } } if (BUFFER_DATA_LENGTH(src) > 0) { cmdErr = COMMAND_OVERFLOW; } } GEOZ_UNLOCK break; case GEOF_CMD_REMOVE: // Remove specified GeoZone(terminal) ID from table cmdErr = COMMAND_OK; GEOZ_LOCK { if (BUFFER_DATA_LENGTH(src) == 0) { // this will remove ALL Geozones! _geozRemoveGeoZone((GeoZoneID_t)NO_ZONE); } else { while (BUFFER_DATA_LENGTH(src) >= sizeof(GeoZoneID_t)) { UInt32 zoneID = 0L; binBufScanf(src, "%*x", sizeof(GeoZoneID_t), &zoneID); _geozRemoveGeoZone((GeoZoneID_t)zoneID); } if (BUFFER_DATA_LENGTH(src) > 0) { cmdErr = COMMAND_OVERFLOW; } } } GEOZ_UNLOCK break; case GEOF_CMD_SAVE: // Save GeoZone table to predefined location. GEOZ_LOCK { cmdErr = _geozSaveGeoZones(GEOZONE_FILENAME)? COMMAND_OK_ACK : // COMMAND_OK; COMMAND_EXECUTION; // not saved } GEOZ_UNLOCK break; default: cmdErr = COMMAND_FEATURE_NOT_SUPPORTED; break; } /* return error */ return cmdErr;}// ----------------------------------------------------------------------------/* initialize geofence module */void geozInitialize(eventAddFtn_t queueEvent){ /* already initialized? */ if (didInitialize) { return; // init only once } didInitialize = utTrue; /* event generator */ ftnQueueEvent = queueEvent; /* init lock */#ifdef ENABLE_THREADS threadMutexInit(&geozMutex);#endif /* init vars */ gpsClear(&arrivePoint); gpsClear(&departPoint); _geozLoadGeoZones(GEOZONE_FILENAME); /* set geozone property command handler */ propSetCommandFtn(PROP_CMD_GEOF_ADMIN, &_cmdGeoZoneAdmin); /* debug stuff */ //GeoZone_t _gz, *gz = &_gz; //logDEBUG(LOGSRC,"sizeof(GeoZone_t) = %d", sizeof(_gz)); //logDEBUG(LOGSRC,"sizeof(GeoZone_t.point) = %d", sizeof(gz->point)); //logDEBUG(LOGSRC,"addr(&(GeoZone_t.point)) = %ld", (UInt32)((UInt32)&(gz->point) - (UInt32)gz));}// ----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -