holosphere 1.1.7 → 1.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/holosphere.js +24 -18
- package/package.json +1 -4
- package/babel.config.js +0 -5
- package/babel.config.json +0 -12
- package/config/default.js +0 -1
- package/examples/README-environmental.md +0 -158
- package/examples/environmentalData.js +0 -380
- package/examples/queryEnvironmentalData.js +0 -147
- package/services/environmentalApi.js +0 -415
- package/services/environmentalApi.test.js +0 -158
- package/test/ai.test.js +0 -425
- package/test/sea.html +0 -33
package/holosphere.js
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
import * as h3 from 'h3-js';
|
|
2
2
|
import OpenAI from 'openai';
|
|
3
3
|
import Gun from 'gun'
|
|
4
|
-
import SEA from 'gun/sea.js'
|
|
5
4
|
import Ajv2019 from 'ajv/dist/2019.js'
|
|
6
5
|
import * as Federation from './federation.js';
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* HoloSphere is a cutting-edge holonic communication infrastructure designed to facilitate
|
|
9
|
+
* the creation, validation, and sharing of information.. By leveraging advanced technologies
|
|
10
|
+
* such as H3 for geospatial indexing, OpenAI for natural language processing, and Gun for decentralized
|
|
11
|
+
* data storage, HoloSphere provides a robust platform for developers to build innovative stygmergic applications.
|
|
12
|
+
*
|
|
13
|
+
* Key Features:
|
|
14
|
+
* - Geospatial indexing using H3
|
|
15
|
+
* - Natural language processing with OpenAI
|
|
16
|
+
* - Decentralized data storage with Gun
|
|
17
|
+
* - JSON schema validation with Ajv
|
|
18
|
+
* - Federation capabilities for distributed systems
|
|
19
|
+
*
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
9
22
|
|
|
10
23
|
class HoloSphere {
|
|
11
24
|
/**
|
|
@@ -15,8 +28,8 @@ class HoloSphere {
|
|
|
15
28
|
* @param {string|null} openaikey - The OpenAI API key.
|
|
16
29
|
* @param {Gun|null} gunInstance - The Gun instance to use.
|
|
17
30
|
*/
|
|
18
|
-
constructor(appname, strict = false, openaikey = null
|
|
19
|
-
console.log('HoloSphere v1.1.
|
|
31
|
+
constructor(appname, strict = false, openaikey = null) {
|
|
32
|
+
console.log('HoloSphere v1.1.9');
|
|
20
33
|
this.appname = appname
|
|
21
34
|
this.strict = strict;
|
|
22
35
|
this.validator = new Ajv2019({
|
|
@@ -25,20 +38,13 @@ class HoloSphere {
|
|
|
25
38
|
validateSchema: true // Always validate schemas
|
|
26
39
|
});
|
|
27
40
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
peers: ['https://gun.holons.io/gun'],
|
|
36
|
-
axe: false,
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Initialize SEA
|
|
41
|
-
this.sea = SEA;
|
|
41
|
+
|
|
42
|
+
// Use provided Gun instance or create new one with default options
|
|
43
|
+
this.gun = Gun({
|
|
44
|
+
peers: ['https://gun.holons.io/gun'],
|
|
45
|
+
axe: false,
|
|
46
|
+
});
|
|
47
|
+
|
|
42
48
|
|
|
43
49
|
if (openaikey != null) {
|
|
44
50
|
this.openai = new OpenAI({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "holosphere",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"description": "Holonic Geospatial Communication Infrastructure",
|
|
5
5
|
"main": "holosphere.js",
|
|
6
6
|
"types": "holosphere.d.ts",
|
|
@@ -14,14 +14,11 @@
|
|
|
14
14
|
"license": "GPL-3.0-or-later",
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"ajv": "^8.12.0",
|
|
17
|
-
"axios": "^1.6.7",
|
|
18
|
-
"dotenv": "^16.4.7",
|
|
19
17
|
"gun": "^0.2020.1240",
|
|
20
18
|
"h3-js": "^4.1.0",
|
|
21
19
|
"openai": "^4.85.1"
|
|
22
20
|
},
|
|
23
21
|
"devDependencies": {
|
|
24
|
-
"@babel/preset-env": "^7.24.0",
|
|
25
22
|
"jest": "^29.7.0",
|
|
26
23
|
"jest-environment-node": "^29.7.0"
|
|
27
24
|
},
|
package/babel.config.js
DELETED
package/babel.config.json
DELETED
package/config/default.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
# HoloSphere Environmental Data Examples
|
|
2
|
-
|
|
3
|
-
This directory contains examples demonstrating how to use HoloSphere for storing, federating, and querying environmental data across different geographical scales.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The examples show how to:
|
|
8
|
-
|
|
9
|
-
1. Store environmental data from various APIs into hierarchical holons
|
|
10
|
-
2. Create federation relationships between holons at different scales
|
|
11
|
-
3. Use soul references to efficiently share data between holons
|
|
12
|
-
4. Query environmental data, including resolving federation references
|
|
13
|
-
5. Compute aggregated metrics across holons
|
|
14
|
-
|
|
15
|
-
## Files
|
|
16
|
-
|
|
17
|
-
- `environmentalData.js` - Shows how to fetch, transform and store environmental data in HoloSphere
|
|
18
|
-
- `queryEnvironmentalData.js` - Demonstrates how to query the stored data across federated holons
|
|
19
|
-
|
|
20
|
-
## Environmental Data Structure
|
|
21
|
-
|
|
22
|
-
The examples organize environmental data into a hierarchical structure:
|
|
23
|
-
|
|
24
|
-
- **City level (H3 resolution 7)**: Air quality data
|
|
25
|
-
- **Region level (H3 resolution 5)**: Carbon sequestration and soil data
|
|
26
|
-
- **Country level (H3 resolution 3)**: Biodiversity data
|
|
27
|
-
|
|
28
|
-
Federation relationships are established between these levels, allowing data to flow from smaller to larger scales while maintaining a single source of truth through soul references.
|
|
29
|
-
|
|
30
|
-
## Data Schemas
|
|
31
|
-
|
|
32
|
-
The examples define several schemas for environmental data:
|
|
33
|
-
|
|
34
|
-
### Air Quality Schema
|
|
35
|
-
```json
|
|
36
|
-
{
|
|
37
|
-
"id": "string",
|
|
38
|
-
"holon": "string",
|
|
39
|
-
"timestamp": "number",
|
|
40
|
-
"coordinates": {
|
|
41
|
-
"lat": "number",
|
|
42
|
-
"lon": "number"
|
|
43
|
-
},
|
|
44
|
-
"airQualityIndex": "number",
|
|
45
|
-
"pollutants": {
|
|
46
|
-
"co": "number",
|
|
47
|
-
"no2": "number",
|
|
48
|
-
"o3": "number",
|
|
49
|
-
"pm2_5": "number",
|
|
50
|
-
"pm10": "number",
|
|
51
|
-
"so2": "number"
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### Carbon Sequestration Schema
|
|
57
|
-
```json
|
|
58
|
-
{
|
|
59
|
-
"id": "string",
|
|
60
|
-
"holon": "string",
|
|
61
|
-
"timestamp": "number",
|
|
62
|
-
"coordinates": {
|
|
63
|
-
"lat": "number",
|
|
64
|
-
"lon": "number"
|
|
65
|
-
},
|
|
66
|
-
"carbonSequestration": "number",
|
|
67
|
-
"temperature": "number",
|
|
68
|
-
"precipitation": "number"
|
|
69
|
-
}
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### Soil Carbon Schema
|
|
73
|
-
```json
|
|
74
|
-
{
|
|
75
|
-
"id": "string",
|
|
76
|
-
"holon": "string",
|
|
77
|
-
"timestamp": "number",
|
|
78
|
-
"coordinates": {
|
|
79
|
-
"lat": "number",
|
|
80
|
-
"lon": "number"
|
|
81
|
-
},
|
|
82
|
-
"soilCarbon": "number",
|
|
83
|
-
"soilType": "string",
|
|
84
|
-
"soilDepth": "string"
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Biodiversity Schema
|
|
89
|
-
```json
|
|
90
|
-
{
|
|
91
|
-
"id": "string",
|
|
92
|
-
"holon": "string",
|
|
93
|
-
"timestamp": "number",
|
|
94
|
-
"countryCode": "string",
|
|
95
|
-
"biodiversityCount": "number",
|
|
96
|
-
"species": [
|
|
97
|
-
{
|
|
98
|
-
"scientificName": "string",
|
|
99
|
-
"count": "number"
|
|
100
|
-
}
|
|
101
|
-
]
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Running the Examples
|
|
106
|
-
|
|
107
|
-
1. Make sure you have all required API keys in your `.env` file:
|
|
108
|
-
- `OPENWEATHER_API_KEY` - For air quality data
|
|
109
|
-
- `NOAA_API_KEY` - For climate data
|
|
110
|
-
|
|
111
|
-
2. Run the data storage example:
|
|
112
|
-
```
|
|
113
|
-
node examples/environmentalData.js
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
3. Run the query example:
|
|
117
|
-
```
|
|
118
|
-
node examples/queryEnvironmentalData.js
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## Federation in Practice
|
|
122
|
-
|
|
123
|
-
These examples demonstrate several key federation concepts:
|
|
124
|
-
|
|
125
|
-
1. **Hierarchical Data Organization**: Environmental data is organized by geographical scale, with relationships between scales.
|
|
126
|
-
|
|
127
|
-
2. **Soul References**: When propagating data from city to region level, soul references are used instead of duplicating data.
|
|
128
|
-
|
|
129
|
-
3. **Automatic Reference Resolution**: When querying data, references are automatically resolved to their original source.
|
|
130
|
-
|
|
131
|
-
4. **Cross-Scale Aggregation**: The compute function is used to aggregate metrics from different scales.
|
|
132
|
-
|
|
133
|
-
## Example Output
|
|
134
|
-
|
|
135
|
-
Running the query example should produce output similar to:
|
|
136
|
-
|
|
137
|
-
```
|
|
138
|
-
Querying environmental data for location (41.9, 12.5)
|
|
139
|
-
- City: 8773237a267ffff
|
|
140
|
-
- Region: 852e3ffffffffffffff
|
|
141
|
-
- Country: 832ffffffffffffffff
|
|
142
|
-
|
|
143
|
-
=== CITY LEVEL: Air Quality Data ===
|
|
144
|
-
Latest Air Quality Index: 2
|
|
145
|
-
Pollutant levels:
|
|
146
|
-
- co: 201.94
|
|
147
|
-
- no2: 0.78
|
|
148
|
-
- o3: 68.64
|
|
149
|
-
- pm2_5: 0.5
|
|
150
|
-
- pm10: 0.82
|
|
151
|
-
- so2: 0.52
|
|
152
|
-
|
|
153
|
-
=== REGION LEVEL: Soil Carbon Data ===
|
|
154
|
-
Soil Carbon: 78.4 g/kg
|
|
155
|
-
Soil Type: Clay Loam
|
|
156
|
-
Soil Depth: 0-30cm
|
|
157
|
-
|
|
158
|
-
...
|
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
import HoloSphere from '../holosphere.js';
|
|
2
|
-
import * as environmentalApi from '../services/environmentalApi.js';
|
|
3
|
-
import * as h3 from 'h3-js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Example script demonstrating how to save environmental data to HoloSphere
|
|
7
|
-
* This creates a structured dataset that can be federated across different holons
|
|
8
|
-
*/
|
|
9
|
-
async function storeEnvironmentalData() {
|
|
10
|
-
// Initialize HoloSphere
|
|
11
|
-
const holosphere = new HoloSphere('environmental-data', true);
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
// Define schemas for different environmental data types
|
|
15
|
-
await setupSchemas(holosphere);
|
|
16
|
-
|
|
17
|
-
// Example coordinates (Rome, Italy)
|
|
18
|
-
const lat = 41.9;
|
|
19
|
-
const lon = 12.5;
|
|
20
|
-
const countryCode = 'ITA';
|
|
21
|
-
|
|
22
|
-
// Get the H3 index for this location at different resolutions
|
|
23
|
-
const cityHolon = await holosphere.getHolon(lat, lon, 7); // City level
|
|
24
|
-
const regionHolon = await holosphere.getHolon(lat, lon, 5); // Region level
|
|
25
|
-
const countryHolon = await holosphere.getHolon(lat, lon, 3); // Country level
|
|
26
|
-
|
|
27
|
-
console.log(`Processing data for holons:
|
|
28
|
-
- City: ${cityHolon}
|
|
29
|
-
- Region: ${regionHolon}
|
|
30
|
-
- Country: ${countryHolon}`);
|
|
31
|
-
|
|
32
|
-
// Set up federation between different levels
|
|
33
|
-
await holosphere.federate(cityHolon, regionHolon);
|
|
34
|
-
await holosphere.federate(regionHolon, countryHolon);
|
|
35
|
-
|
|
36
|
-
// Fetch environmental data
|
|
37
|
-
console.log('Fetching environmental data...');
|
|
38
|
-
|
|
39
|
-
// Air quality data (city level)
|
|
40
|
-
let airQualityRecord;
|
|
41
|
-
const airQualityData = await environmentalApi.getAirQuality(lat, lon);
|
|
42
|
-
if (airQualityData) {
|
|
43
|
-
airQualityRecord = transformAirQualityData(airQualityData, cityHolon);
|
|
44
|
-
await holosphere.put(cityHolon, 'air-quality', airQualityRecord);
|
|
45
|
-
console.log('Stored air quality data in city holon');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Carbon sequestration data (region level)
|
|
49
|
-
const carbonData = await environmentalApi.getCarbonSequestration(lat, lon);
|
|
50
|
-
if (carbonData) {
|
|
51
|
-
const carbonRecord = transformCarbonData(carbonData, regionHolon);
|
|
52
|
-
await holosphere.put(regionHolon, 'carbon-sequestration', carbonRecord);
|
|
53
|
-
console.log('Stored carbon sequestration data in region holon');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Soil carbon data (region level)
|
|
57
|
-
const soilCarbonData = await environmentalApi.getSoilCarbon(lat, lon);
|
|
58
|
-
if (soilCarbonData) {
|
|
59
|
-
const soilCarbonRecord = transformSoilCarbonData(soilCarbonData, regionHolon);
|
|
60
|
-
await holosphere.put(regionHolon, 'soil-data', soilCarbonRecord);
|
|
61
|
-
console.log('Stored soil carbon data in region holon');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Biodiversity data (country level)
|
|
65
|
-
const biodiversityData = await environmentalApi.getBiodiversityData(countryCode);
|
|
66
|
-
if (biodiversityData) {
|
|
67
|
-
const biodiversityRecord = transformBiodiversityData(biodiversityData, countryHolon);
|
|
68
|
-
await holosphere.put(countryHolon, 'biodiversity', biodiversityRecord);
|
|
69
|
-
console.log('Stored biodiversity data in country holon');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Define and add the environmental metrics schema
|
|
73
|
-
const metricsSchema = {
|
|
74
|
-
type: 'object',
|
|
75
|
-
properties: {
|
|
76
|
-
id: { type: 'string' },
|
|
77
|
-
holon: { type: 'string' },
|
|
78
|
-
timestamp: { type: 'number' },
|
|
79
|
-
metrics: {
|
|
80
|
-
type: 'object',
|
|
81
|
-
properties: {
|
|
82
|
-
airQualityIndex: { type: 'number' },
|
|
83
|
-
carbonSequestration: { type: 'number' },
|
|
84
|
-
soilCarbon: { type: 'number' },
|
|
85
|
-
biodiversityCount: { type: 'number' }
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
required: ['id', 'holon', 'timestamp', 'metrics']
|
|
90
|
-
};
|
|
91
|
-
await holosphere.setSchema('environmental-metrics', metricsSchema);
|
|
92
|
-
console.log('Set schema for environmental metrics');
|
|
93
|
-
|
|
94
|
-
// Create initial empty metrics object
|
|
95
|
-
const metricsRecord = {
|
|
96
|
-
id: `env-metrics-${Date.now()}`,
|
|
97
|
-
holon: countryHolon,
|
|
98
|
-
timestamp: Date.now(),
|
|
99
|
-
metrics: {
|
|
100
|
-
airQualityIndex: 0,
|
|
101
|
-
carbonSequestration: 0,
|
|
102
|
-
soilCarbon: 0,
|
|
103
|
-
biodiversityCount: 0
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
await holosphere.put(countryHolon, 'environmental-metrics', metricsRecord);
|
|
107
|
-
console.log('Added initial environmental metrics record');
|
|
108
|
-
|
|
109
|
-
// Propagate data to create federation references
|
|
110
|
-
console.log('Setting up data federation...');
|
|
111
|
-
|
|
112
|
-
// Propagate air quality data up to region
|
|
113
|
-
if (airQualityRecord) {
|
|
114
|
-
await holosphere.propagate(cityHolon, 'air-quality', airQualityRecord, {
|
|
115
|
-
targetSpaces: [regionHolon]
|
|
116
|
-
});
|
|
117
|
-
console.log('Propagated air quality data to region holon');
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Aggregate environmental metrics at country level - manual approach since compute has issues
|
|
121
|
-
console.log('Manually updating environmental metrics...');
|
|
122
|
-
try {
|
|
123
|
-
// Get data from various sources
|
|
124
|
-
const airData = airQualityRecord || { airQualityIndex: 0 };
|
|
125
|
-
const carbonData = await holosphere.get(regionHolon, 'carbon-sequestration');
|
|
126
|
-
const soilData = await holosphere.get(regionHolon, 'soil-data');
|
|
127
|
-
const bioData = await holosphere.get(countryHolon, 'biodiversity');
|
|
128
|
-
|
|
129
|
-
// Update metrics manually
|
|
130
|
-
const updatedMetrics = {
|
|
131
|
-
id: metricsRecord.id,
|
|
132
|
-
holon: countryHolon,
|
|
133
|
-
timestamp: Date.now(),
|
|
134
|
-
metrics: {
|
|
135
|
-
airQualityIndex: airData.airQualityIndex || 0,
|
|
136
|
-
carbonSequestration: carbonData?.carbonSequestration || 0,
|
|
137
|
-
soilCarbon: soilData?.soilCarbon || 0,
|
|
138
|
-
biodiversityCount: bioData?.biodiversityCount || 0
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
await holosphere.put(countryHolon, 'environmental-metrics', updatedMetrics);
|
|
143
|
-
console.log('Updated environmental metrics at country level:', updatedMetrics);
|
|
144
|
-
} catch (updateError) {
|
|
145
|
-
console.error('Error updating environmental metrics:', updateError);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Get and display the metrics directly instead of using getFederated
|
|
149
|
-
console.log('Retrieving environmental metrics...');
|
|
150
|
-
try {
|
|
151
|
-
const environmentalMetrics = await holosphere.get(countryHolon, 'environmental-metrics');
|
|
152
|
-
console.log('Environmental metrics:', environmentalMetrics);
|
|
153
|
-
} catch (getError) {
|
|
154
|
-
console.error('Error retrieving metrics:', getError);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
} catch (error) {
|
|
158
|
-
console.error('Error storing environmental data:', error);
|
|
159
|
-
} finally {
|
|
160
|
-
// Close HoloSphere instance
|
|
161
|
-
await holosphere.close();
|
|
162
|
-
console.log('HoloSphere instance closed successfully');
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Set up schemas for environmental data
|
|
168
|
-
*/
|
|
169
|
-
async function setupSchemas(holosphere) {
|
|
170
|
-
// Air quality schema
|
|
171
|
-
const airQualitySchema = {
|
|
172
|
-
type: 'object',
|
|
173
|
-
properties: {
|
|
174
|
-
id: { type: 'string' },
|
|
175
|
-
holon: { type: 'string' },
|
|
176
|
-
timestamp: { type: 'number' },
|
|
177
|
-
coordinates: {
|
|
178
|
-
type: 'object',
|
|
179
|
-
properties: {
|
|
180
|
-
lat: { type: 'number' },
|
|
181
|
-
lon: { type: 'number' }
|
|
182
|
-
}
|
|
183
|
-
},
|
|
184
|
-
airQualityIndex: { type: 'number' },
|
|
185
|
-
pollutants: {
|
|
186
|
-
type: 'object',
|
|
187
|
-
properties: {
|
|
188
|
-
co: { type: 'number' },
|
|
189
|
-
no2: { type: 'number' },
|
|
190
|
-
o3: { type: 'number' },
|
|
191
|
-
pm2_5: { type: 'number' },
|
|
192
|
-
pm10: { type: 'number' },
|
|
193
|
-
so2: { type: 'number' }
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
},
|
|
197
|
-
required: ['id', 'holon', 'timestamp', 'coordinates', 'airQualityIndex']
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
// Carbon sequestration schema
|
|
201
|
-
const carbonSchema = {
|
|
202
|
-
type: 'object',
|
|
203
|
-
properties: {
|
|
204
|
-
id: { type: 'string' },
|
|
205
|
-
holon: { type: 'string' },
|
|
206
|
-
timestamp: { type: 'number' },
|
|
207
|
-
coordinates: {
|
|
208
|
-
type: 'object',
|
|
209
|
-
properties: {
|
|
210
|
-
lat: { type: 'number' },
|
|
211
|
-
lon: { type: 'number' }
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
carbonSequestration: { type: 'number' },
|
|
215
|
-
temperature: { type: 'number' },
|
|
216
|
-
precipitation: { type: 'number' }
|
|
217
|
-
},
|
|
218
|
-
required: ['id', 'holon', 'timestamp', 'coordinates', 'carbonSequestration']
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
// Soil carbon schema
|
|
222
|
-
const soilSchema = {
|
|
223
|
-
type: 'object',
|
|
224
|
-
properties: {
|
|
225
|
-
id: { type: 'string' },
|
|
226
|
-
holon: { type: 'string' },
|
|
227
|
-
timestamp: { type: 'number' },
|
|
228
|
-
coordinates: {
|
|
229
|
-
type: 'object',
|
|
230
|
-
properties: {
|
|
231
|
-
lat: { type: 'number' },
|
|
232
|
-
lon: { type: 'number' }
|
|
233
|
-
}
|
|
234
|
-
},
|
|
235
|
-
soilCarbon: { type: 'number' },
|
|
236
|
-
soilType: { type: 'string' },
|
|
237
|
-
soilDepth: { type: 'string' }
|
|
238
|
-
},
|
|
239
|
-
required: ['id', 'holon', 'timestamp', 'coordinates', 'soilCarbon']
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
// Biodiversity schema
|
|
243
|
-
const biodiversitySchema = {
|
|
244
|
-
type: 'object',
|
|
245
|
-
properties: {
|
|
246
|
-
id: { type: 'string' },
|
|
247
|
-
holon: { type: 'string' },
|
|
248
|
-
timestamp: { type: 'number' },
|
|
249
|
-
countryCode: { type: 'string' },
|
|
250
|
-
biodiversityCount: { type: 'number' },
|
|
251
|
-
species: {
|
|
252
|
-
type: 'array',
|
|
253
|
-
items: {
|
|
254
|
-
type: 'object',
|
|
255
|
-
properties: {
|
|
256
|
-
scientificName: { type: 'string' },
|
|
257
|
-
count: { type: 'number' }
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
},
|
|
262
|
-
required: ['id', 'holon', 'timestamp', 'countryCode', 'biodiversityCount']
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
// Set schemas
|
|
266
|
-
await holosphere.setSchema('air-quality', airQualitySchema);
|
|
267
|
-
await holosphere.setSchema('carbon-sequestration', carbonSchema);
|
|
268
|
-
await holosphere.setSchema('soil-data', soilSchema);
|
|
269
|
-
await holosphere.setSchema('biodiversity', biodiversitySchema);
|
|
270
|
-
|
|
271
|
-
console.log('Environmental data schemas set up successfully');
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* Transform air quality data from API into our schema
|
|
276
|
-
*/
|
|
277
|
-
function transformAirQualityData(apiData, holon) {
|
|
278
|
-
const components = apiData.list?.[0]?.components || {};
|
|
279
|
-
const main = apiData.list?.[0]?.main || {};
|
|
280
|
-
|
|
281
|
-
return {
|
|
282
|
-
id: `air-quality-${Date.now()}`,
|
|
283
|
-
holon: holon,
|
|
284
|
-
timestamp: Date.now(),
|
|
285
|
-
coordinates: {
|
|
286
|
-
lat: apiData.coord?.lat || 0,
|
|
287
|
-
lon: apiData.coord?.lon || 0
|
|
288
|
-
},
|
|
289
|
-
airQualityIndex: main.aqi || 0,
|
|
290
|
-
pollutants: {
|
|
291
|
-
co: components.co || 0,
|
|
292
|
-
no2: components.no2 || 0,
|
|
293
|
-
o3: components.o3 || 0,
|
|
294
|
-
pm2_5: components.pm2_5 || 0,
|
|
295
|
-
pm10: components.pm10 || 0,
|
|
296
|
-
so2: components.so2 || 0
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Transform carbon sequestration data from API into our schema
|
|
303
|
-
*/
|
|
304
|
-
function transformCarbonData(apiData, holon) {
|
|
305
|
-
const parameters = apiData.properties?.parameter || {};
|
|
306
|
-
const temperature = parameters.T2M?.['20230701'] || 0;
|
|
307
|
-
const precipitation = parameters.PRECTOT?.['20230701'] || 0;
|
|
308
|
-
|
|
309
|
-
// Calculate a simplified carbon sequestration estimate
|
|
310
|
-
// (In a real app, use actual models based on temperature, precipitation, etc.)
|
|
311
|
-
const carbonSequestration = (temperature * 0.5) + (precipitation * 2);
|
|
312
|
-
|
|
313
|
-
return {
|
|
314
|
-
id: `carbon-seq-${Date.now()}`,
|
|
315
|
-
holon: holon,
|
|
316
|
-
timestamp: Date.now(),
|
|
317
|
-
coordinates: {
|
|
318
|
-
lat: apiData.geometry?.coordinates[1] || 0,
|
|
319
|
-
lon: apiData.geometry?.coordinates[0] || 0
|
|
320
|
-
},
|
|
321
|
-
carbonSequestration: carbonSequestration,
|
|
322
|
-
temperature: temperature,
|
|
323
|
-
precipitation: precipitation
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Transform soil carbon data from API into our schema
|
|
329
|
-
*/
|
|
330
|
-
function transformSoilCarbonData(apiData, holon) {
|
|
331
|
-
const properties = apiData.properties || {};
|
|
332
|
-
const soilCarbon = properties.soilGrids?.properties?.soc?.mean || 0;
|
|
333
|
-
|
|
334
|
-
return {
|
|
335
|
-
id: `soil-carbon-${Date.now()}`,
|
|
336
|
-
holon: holon,
|
|
337
|
-
timestamp: Date.now(),
|
|
338
|
-
coordinates: {
|
|
339
|
-
lat: apiData.geometry?.coordinates[1] || 0,
|
|
340
|
-
lon: apiData.geometry?.coordinates[0] || 0
|
|
341
|
-
},
|
|
342
|
-
soilCarbon: soilCarbon,
|
|
343
|
-
soilType: properties.soilType || 'Unknown',
|
|
344
|
-
soilDepth: '0-30cm'
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
/**
|
|
349
|
-
* Transform biodiversity data from API into our schema
|
|
350
|
-
*/
|
|
351
|
-
function transformBiodiversityData(apiData, holon) {
|
|
352
|
-
const results = apiData.results || [];
|
|
353
|
-
const species = {};
|
|
354
|
-
|
|
355
|
-
// Count species occurrences
|
|
356
|
-
results.forEach(occurrence => {
|
|
357
|
-
const name = occurrence.scientificName || 'Unknown';
|
|
358
|
-
species[name] = (species[name] || 0) + 1;
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
// Convert to array format
|
|
362
|
-
const speciesArray = Object.keys(species).map(name => ({
|
|
363
|
-
scientificName: name,
|
|
364
|
-
count: species[name]
|
|
365
|
-
}));
|
|
366
|
-
|
|
367
|
-
return {
|
|
368
|
-
id: `biodiversity-${Date.now()}`,
|
|
369
|
-
holon: holon,
|
|
370
|
-
timestamp: Date.now(),
|
|
371
|
-
countryCode: results[0]?.countryCode || 'Unknown',
|
|
372
|
-
biodiversityCount: results.length,
|
|
373
|
-
species: speciesArray
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// Execute the example
|
|
378
|
-
storeEnvironmentalData()
|
|
379
|
-
.then(() => console.log('Environmental data example completed'))
|
|
380
|
-
.catch(error => console.error('Error in environmental data example:', error));
|