EXAMPLE #07
PHP
Bash
Reusable client
A reusable PHP class and Bash function set for any script.
07-reusable-client.php
#!/usr/bin/env php
<?php
/**
* Example: Reusable client class for the Space Place API
*
* Wraps authentication and event creation into a simple class that can be
* dropped into any PHP project.
*
* Usage:
* php 07-reusable-client.php
*
* // Or require it from another script:
* require_once __DIR__ . '/07-reusable-client.php';
* $client = new SpacePlaceClient('http://...', 'ds-uuid', 'token-value');
* $client->sendEvent(number: 1, key: 'metric', value: '99');
*/
class SpacePlaceClient
{
public function __construct(
private string $baseUrl,
private string $dataStreamId,
private string $tokenValue,
private int $timeout = 10,
) {}
/**
* Send a single event.
*
* @return array{success: bool, event_id: ?string, timestamp: ?string, error: ?string}
*/
public function sendEvent(
int $number = 0,
string $source = '',
string $key = '',
string $value = '',
?string $timestamp = null,
): array {
$payload = compact('number', 'source', 'key', 'value');
if ($timestamp !== null) {
$payload['timestamp'] = $timestamp;
}
return $this->post('/api/events', $payload);
}
/**
* Send multiple events. Returns an array of results, one per event.
*
* @param array<array{number?: int, source?: string, key?: string, value?: string, timestamp?: string}> $events
* @return array<array{success: bool, event_id: ?string, timestamp: ?string, error: ?string}>
*/
public function sendBatch(array $events): array
{
$results = [];
foreach ($events as $event) {
$results[] = $this->sendEvent(
number: $event['number'] ?? 0,
source: $event['source'] ?? '',
key: $event['key'] ?? '',
value: $event['value'] ?? '',
timestamp: $event['timestamp'] ?? null,
);
}
return $results;
}
private function post(string $path, array $payload): array
{
$ch = curl_init("{$this->baseUrl}{$path}");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Accept: application/json',
"X-DataStream-ID: {$this->dataStreamId}",
"X-Token: {$this->tokenValue}",
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
return ['success' => false, 'event_id' => null, 'timestamp' => null, 'error' => "cURL: {$error}"];
}
$body = json_decode($response, true) ?? [];
if ($httpCode === 201) {
return [
'success' => true,
'event_id' => $body['event_id'] ?? null,
'timestamp' => $body['timestamp'] ?? null,
'error' => null,
];
}
return [
'success' => false,
'event_id' => null,
'timestamp' => null,
'error' => "HTTP {$httpCode}: " . ($body['error'] ?? $body['message'] ?? $response),
];
}
}
// ── Demo usage ───────────────────────────────────────────────────────────────
// Only run the demo when this file is executed directly
if (realpath($argv[0] ?? '') === realpath(__FILE__)) {
$client = new SpacePlaceClient(
baseUrl: 'https://www.spaceplace.app',
dataStreamId: 'YOUR-DATASTREAM-UUID-HERE',
tokenValue: 'YOUR-TOKEN-VALUE-HERE',
);
// Single event
echo "Sending single event...\n";
$result = $client->sendEvent(number: 1, source: 'client-demo', key: 'ping', value: 'pong');
if ($result['success']) {
echo " Created: {$result['event_id']}\n";
} else {
echo " Error: {$result['error']}\n";
}
// Batch of events
echo "\nSending batch of 3 events...\n";
$results = $client->sendBatch([
['number' => 1, 'source' => 'client-demo', 'key' => 'cpu', 'value' => '45.2'],
['number' => 2, 'source' => 'client-demo', 'key' => 'memory', 'value' => '72.8'],
['number' => 3, 'source' => 'client-demo', 'key' => 'disk', 'value' => '31.0'],
]);
foreach ($results as $i => $r) {
$status = $r['success'] ? "OK ({$r['event_id']})" : "FAIL ({$r['error']})";
echo " Event " . ($i + 1) . ": {$status}\n";
}
}
07-reusable-functions.sh
#!/usr/bin/env bash
#
# Example: Reusable functions for the Space Place API
#
# Source this file from other scripts, or run it directly for a demo.
#
# Usage:
# bash 07-reusable-functions.sh
#
# # Or source from another script:
# source ./07-reusable-functions.sh
# sp_configure "https://www.spaceplace.app" "ds-uuid" "token-value"
# sp_send_event 1 "my-source" "metric" "99"
SP_BASE_URL=""
SP_DATASTREAM_ID=""
SP_TOKEN_VALUE=""
sp_configure() {
SP_BASE_URL="$1"
SP_DATASTREAM_ID="$2"
SP_TOKEN_VALUE="$3"
}
# Send a single event. Returns 0 on success, 1 on failure.
# Usage: sp_send_event <number> <source> <key> <value> [timestamp]
sp_send_event() {
local number="${1:-0}"
local source="${2:-}"
local key="${3:-}"
local value="${4:-}"
local timestamp="${5:-}"
local ts_field=""
if [ -n "$timestamp" ]; then
ts_field="\"timestamp\": \"${timestamp}\","
fi
local response
response=$(curl -s -w "\n%{http_code}" --max-time 10 \
-X POST "${SP_BASE_URL}/api/events" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-DataStream-ID: ${SP_DATASTREAM_ID}" \
-H "X-Token: ${SP_TOKEN_VALUE}" \
-d "{
${ts_field}
\"number\": ${number},
\"source\": \"${source}\",
\"key\": \"${key}\",
\"value\": \"${value}\"
}")
local http_code body
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" = "201" ]; then
SP_LAST_EVENT_ID=$(echo "$body" | jq -r '.event_id')
SP_LAST_TIMESTAMP=$(echo "$body" | jq -r '.timestamp')
return 0
else
SP_LAST_ERROR="HTTP ${http_code}: $(echo "$body" | jq -r '.error // .message // "unknown"')"
return 1
fi
}
# List events. Extra curl args can be appended.
# Usage: sp_list_events [query_string]
# Example: sp_list_events "key=temperature&per_page=10"
sp_list_events() {
local query="${1:-}"
local url="${SP_BASE_URL}/api/events"
[ -n "$query" ] && url="${url}?${query}"
curl -s \
-H "Accept: application/json" \
-H "X-DataStream-ID: ${SP_DATASTREAM_ID}" \
-H "X-Token: ${SP_TOKEN_VALUE}" \
"$url"
}
# Get events since a datetime.
# Usage: sp_events_since <datetime> [extra_query_params]
sp_events_since() {
local since="$1"
local extra="${2:-}"
local query="since=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${since}'))")"
[ -n "$extra" ] && query="${query}&${extra}"
curl -s \
-H "Accept: application/json" \
-H "X-DataStream-ID: ${SP_DATASTREAM_ID}" \
-H "X-Token: ${SP_TOKEN_VALUE}" \
"${SP_BASE_URL}/api/events/since?${query}"
}
# Get a single event.
# Usage: sp_get_event <event-uuid>
sp_get_event() {
curl -s \
-H "Accept: application/json" \
-H "X-DataStream-ID: ${SP_DATASTREAM_ID}" \
-H "X-Token: ${SP_TOKEN_VALUE}" \
"${SP_BASE_URL}/api/events/$1"
}
# Update an event.
# Usage: sp_update_event <event-uuid> <json-payload>
sp_update_event() {
curl -s \
-X PUT \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-DataStream-ID: ${SP_DATASTREAM_ID}" \
-H "X-Token: ${SP_TOKEN_VALUE}" \
-d "$2" \
"${SP_BASE_URL}/api/events/$1"
}
# Delete an event.
# Usage: sp_delete_event <event-uuid>
sp_delete_event() {
curl -s \
-X DELETE \
-H "Accept: application/json" \
-H "X-DataStream-ID: ${SP_DATASTREAM_ID}" \
-H "X-Token: ${SP_TOKEN_VALUE}" \
"${SP_BASE_URL}/api/events/$1"
}
# ── Demo (only runs when executed directly, not when sourced) ─────────────────
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
sp_configure \
"https://www.spaceplace.app" \
"YOUR-DATASTREAM-UUID-HERE" \
"YOUR-TOKEN-VALUE-HERE"
echo "--- Sending single event ---"
if sp_send_event 1 "func-demo" "ping" "pong"; then
echo " Created: ${SP_LAST_EVENT_ID}"
else
echo " Error: ${SP_LAST_ERROR}"
fi
echo ""
echo "--- Sending batch of 3 events ---"
for metric in "cpu:45.2" "memory:72.8" "disk:31.0"; do
key="${metric%%:*}"
val="${metric##*:}"
if sp_send_event 0 "func-demo" "$key" "$val"; then
echo " ${key}: OK (${SP_LAST_EVENT_ID})"
else
echo " ${key}: FAIL (${SP_LAST_ERROR})"
fi
done
fi