Open hitchanatanael opened 1 month ago
Perhaps the problem is that the WITHIN POINT command requires that the coordinates are lat/lon. You have lon/lat.
The geojson appears to be in the correct order to me.
$geoJson = [
'type' => 'Polygon',
'coordinates' => [
[
[101.37970257356153, 0.478055156390471],
[101.37975609768263, 0.4780623891280328],
[101.37977851994957, 0.47807034513933927],
[101.37982408778241, 0.47802839526145813],
[101.37982408778241, 0.478007420322403],
[101.37982625767923, 0.4779604075277617],
[101.37978141314531, 0.4779437722311241],
[101.37974597149756, 0.4779524515163407],
[101.37970691335514, 0.4779871686570672],
[101.37970257356153, 0.478055156390471]
]
]
];
I only issue I see is with the WITHIN
command.
$withinCommand = ['WITHIN', 'geofence', 'POINT', $longitude, $latitude];
It should be:
$withinCommand = ['WITHIN', 'geofence', 'POINT', $latitude, $longitude];
No idea what I was thinking. Shouldn’t answer GitHub issues first thing in the morning. 🙃🙂
One other thing. The WITHIN command as shown is attempting to find objects from the “geofences” collection that are “within” a POINT. That may not give the results that you want.
If what you are trying to do is to find which polygon geofences contain a specific point then I recommend using the INTERSECTS instead.
Previously I had also changed from longitude latitude to longitude latitude, and the results were still the same.
here is the generated laravel log: [2024-07-15 06:00:38] local.INFO: Successfully connected to Tile38 [2024-07-15 06:00:38] local.INFO: Tile38 set response {"response":"OK"} [2024-07-15 06:00:38] local.INFO: Tile38 response {"response":[0,[]]} [2024-07-15 06:00:38] local.INFO: User is outside the geofence.
protected $tile38;
public function __construct()
{
try {
$this->tile38 = new Client([
'scheme' => 'tcp',
'host' => config('database.redis.tile38.host'),
'port' => config('database.redis.tile38.port'),
]);
Log::info('Successfully connected to Tile38');
} catch (\Exception $e) {
Log::error('Failed to connect to Tile38: ' . $e->getMessage());
}
}
private function checkGeofence($latitude, $longitude)
{
try {
$pingResponse = $this->tile38->ping();
if ($pingResponse->getPayload() !== 'PONG') {
Log::error('Tidak dapat terhubung ke Tile38.');
return ['status' => false, 'message' => 'Tidak dapat terhubung ke Tile38.'];
}
$geoJson = '{
"type" : "Polygon",
"coordinates" : [
[
[101.3629689712017, 0.46937355787708773],
[101.36295220739564, 0.46947011415901285],
[101.36297098285843, 0.46951839229948555],
[101.3630427319483, 0.46955057772626807],
[101.36313727981437, 0.4695324734237228],
[101.36315069085921, 0.46947883104552296],
[101.36316141969506, 0.4694332350237229],
[101.36313258594868, 0.46935210092537777],
[101.36299713439585, 0.46932527973563537],
[101.3629689712017, 0.46937355787708773]
]
]
}';
$geoJsonString = json_encode(json_decode($geoJson, true));
$setCommand = ['SET', 'geofence', 'mygeofence', 'OBJECT', $geoJsonString];
$setResponse = $this->tile38->executeRaw($setCommand);
Log::info('Tile38 set response', ['response' => $setResponse]);
$withinCommand = ['WITHIN', 'geofence', 'POINT', $latitude, $longitude];
$response = $this->tile38->executeRaw($withinCommand);
Log::info('Tile38 response', ['response' => $response]);
if (isset($response[0]) && $response[0] === 'OK' && count($response) > 1) {
return ['status' => 'success', 'isWithin' => true];
}
return ['status' => 'error', 'message' => 'You are outside the geofence area'];
} catch (\Exception $e) {
Log::error('Error in Geofence check: ' . $e->getMessage());
return ['status' => 'error', 'message' => 'Internal Server Error'];
}
}
Is there a Laravel project that uses tile38 before? I've looked for several sources, and haven't found anyone who has used Laravel. Maybe you have other references, and if you use another programming language that's okay, as long as you use set and within queries. because maybe I still have errors in making the query
Switch WITHIN with INTERSECTS and try again as suggested above. 🙂
A Polygon will never be WITHIN a point, but a Point can INTERSECT a Polygon.
Wow, I am very grateful, finally my project was successfully completed. For geofencing, do I need to send it in this comment? I will immediately send the Laravel controller for geofencing here. once again thank you all
For geofencing, do I need to send it in this comment?
To setup a geofence from that polygon you would do
SETHOOK {your_geofence} {endpoint to send events to} INTERSECT {the collection you want to alert on} OBJECT {your polygon}
// if you already have the geofence in your collection you can also do it like this
// to reuse the geometry you have already stored.
SETHOOK {name of your geofence} {endpoint where to send events to} INTERSECT {the collection you want to alert on} GET geofence mygeofence
e.g. to alert on vehicles in the fleet
collection entering your geofence and sending to an https endpoint you would do
SETHOOK mygeofence https://localhost:3000/my_hook INTERSECTS fleet GET geofence mygeofence
My project using Laravel and Tile38 has been completed, and I also use INTERSECTS according to your suggestion to check whether the user is in the geofencing. Below is the complete code for geofencing:
private function checkGeofence($latitude, $longitude)
{
try {
$pingResponse = $this->tile38->ping();
if ($pingResponse->getPayload() !== 'PONG') {
Log::error('Cannot connect to Tile38.');
return ['status' => false, 'message' => 'Cannot connect to Tile38.'];
}
$geoJson = '{
"type" : "Polygon",
"coordinates" : [
[
[Fill in the coordinates in the order longitude, latitude],
]
]
}';
$geoJsonString = json_encode(json_decode($geoJson, true));
$setCommand = ['SET', 'geofence', 'mygeofence', 'OBJECT', $geoJsonString];
$setResponse = $this->tile38->executeRaw($setCommand);
Log::info('Tile38 set response', ['setResponse' => $setResponse]);
$intersectsCommand = ['INTERSECTS', 'geofence', 'POINT', $latitude, $longitude];
$intersectsResponse = $this->tile38->executeRaw($intersectsCommand);
Log::info('Tile38 response', ['intersectsResponse' => $intersectsResponse]);
if (isset($intersectsResponse[1]) && is_array($intersectsResponse[1]) && count($intersectsResponse[1]) > 0) {
foreach ($intersectsResponse[1] as $result) {
if ($result[0] === 'mygeofence') {
return ['status' => 'success', 'isWithin' => true];
}
}
}
return ['status' => 'error', 'message' => 'You are outside the geofence area'];
} catch (\Exception $e) {
Log::error('Error in Geofence check: ' . $e->getMessage());
return ['status' => 'error', 'message' => 'Internal Server Error'];
}
}
I am experiencing an issue with the
WITHIN
query in Tile38 for geofencing. I have successfully set up the geofence using theSET
command, but when I execute theWITHIN
query, it always returns that the user is outside the geofence, even when the coordinates should be inside the defined area.Here are the details of my setup:
Code: