diff --git a/README.md b/README.md
index fb2ea99..7893a38 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,7 @@ This library supports parsing any valid JSON file using the following schema ver
- v0.13
- v14
+- v15
Note: Endpoints using versions 0.12 and older are not supported, they will
result in a `ParseError` being thrown.
diff --git a/src/main/kotlin/io/spaceapi/types/Area.kt b/src/main/kotlin/io/spaceapi/types/Area.kt
new file mode 100644
index 0000000..c830a7a
--- /dev/null
+++ b/src/main/kotlin/io/spaceapi/types/Area.kt
@@ -0,0 +1,31 @@
+/**
+ * spaceapi-kt
+ * https://github.com/spaceapi-community/spaceapi-kt/
+ * Copyright (C) 2020-2024 Danilo Bargen
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package io.spaceapi.types
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class Area(
+ @JvmField
+ var name: String? = null,
+ @JvmField
+ var description: String? = null,
+ @JvmField
+ var square_meters: Float,
+)
diff --git a/src/main/kotlin/io/spaceapi/types/LinkedSpace.kt b/src/main/kotlin/io/spaceapi/types/LinkedSpace.kt
new file mode 100644
index 0000000..f550d55
--- /dev/null
+++ b/src/main/kotlin/io/spaceapi/types/LinkedSpace.kt
@@ -0,0 +1,29 @@
+/**
+ * spaceapi-kt
+ * https://github.com/spaceapi-community/spaceapi-kt/
+ * Copyright (C) 2020-2024 Danilo Bargen
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package io.spaceapi.types
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class LinkedSpace(
+ @JvmField
+ var website: String? = null,
+ @JvmField
+ var endpoint: String? = null,
+)
diff --git a/src/main/kotlin/io/spaceapi/types/Location.kt b/src/main/kotlin/io/spaceapi/types/Location.kt
index 14ab4c4..841dee2 100644
--- a/src/main/kotlin/io/spaceapi/types/Location.kt
+++ b/src/main/kotlin/io/spaceapi/types/Location.kt
@@ -25,9 +25,15 @@ data class Location(
@JvmField
var address: String? = null,
@JvmField
- var lat: Float,
+ var lat: Float? = null,
@JvmField
- var lon: Float,
+ var lon: Float? = null,
@JvmField
var timezone: String? = null,
+ @JvmField
+ var country_code: String? = null,
+ @JvmField
+ var areas: Array = emptyArray(),
+ @JvmField
+ var hint: String? = null,
)
diff --git a/src/main/kotlin/io/spaceapi/types/Sensors.kt b/src/main/kotlin/io/spaceapi/types/Sensors.kt
index 538f582..ab6af03 100644
--- a/src/main/kotlin/io/spaceapi/types/Sensors.kt
+++ b/src/main/kotlin/io/spaceapi/types/Sensors.kt
@@ -52,6 +52,10 @@ data class Sensors(
var people_now_present: Array = emptyArray(),
@JvmField
var network_traffic: Array = emptyArray(),
+ @JvmField
+ var power_generation: Array = emptyArray(),
+ @JvmField
+ var carbondioxide: Array = emptyArray(),
)
@Serializable
@@ -66,6 +70,8 @@ data class Temperature(
var name: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -78,6 +84,8 @@ data class DoorLocked(
var name: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -92,6 +100,8 @@ data class Barometer(
var name: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -122,6 +132,8 @@ data class RadiationSensor(
var name: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -136,6 +148,8 @@ data class Humidity(
var name: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -150,6 +164,8 @@ data class BeverageSupply(
var name: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -164,6 +180,8 @@ data class PowerConsumption(
var name: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -176,6 +194,8 @@ data class Wind(
var name: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -228,6 +248,8 @@ data class NetworkConnection(
var name: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -250,6 +272,8 @@ data class AccountBalance(
var name: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -262,6 +286,8 @@ data class MemberCount(
var name: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -276,6 +302,8 @@ data class PeoplePresent(
var names: Array = emptyArray(),
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -288,6 +316,8 @@ data class NetworkTraffic(
var location: String? = null,
@JvmField
var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
)
@Serializable
@@ -311,3 +341,35 @@ data class PacketsPerSecond(
@JvmField
var value: Long,
)
+
+@Serializable
+data class PowerGeneration(
+ @JvmField
+ var value: Float,
+ @JvmField
+ var unit: String,
+ @JvmField
+ var location: String,
+ @JvmField
+ var name: String? = null,
+ @JvmField
+ var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
+)
+
+@Serializable
+data class CarbonDioxide(
+ @JvmField
+ var value: Float,
+ @JvmField
+ var unit: String,
+ @JvmField
+ var location: String,
+ @JvmField
+ var name: String? = null,
+ @JvmField
+ var description: String? = null,
+ @JvmField
+ var lastchange: Float? = null,
+)
diff --git a/src/main/kotlin/io/spaceapi/types/Status.kt b/src/main/kotlin/io/spaceapi/types/Status.kt
index 9caa82e..0afcaed 100644
--- a/src/main/kotlin/io/spaceapi/types/Status.kt
+++ b/src/main/kotlin/io/spaceapi/types/Status.kt
@@ -38,7 +38,7 @@ data class Status(
@JvmField
var url: String,
@JvmField
- var location: Location,
+ var location: Location? = null,
@JvmField
var spacefed: SpaceFed? = null,
@JvmField
@@ -71,4 +71,6 @@ data class Status(
@Deprecated("The 'radio_show' field was removed in API v14")
@JvmField
var radio_show: Array = emptyArray(),
+ @JvmField
+ var linked_spaces: Array = emptyArray(),
)
diff --git a/src/test/kotlin/io/spaceapi/ParserTestKotlin.kt b/src/test/kotlin/io/spaceapi/ParserTestKotlin.kt
index aa97175..ed3cca6 100644
--- a/src/test/kotlin/io/spaceapi/ParserTestKotlin.kt
+++ b/src/test/kotlin/io/spaceapi/ParserTestKotlin.kt
@@ -46,9 +46,9 @@ class ParserTestKotlin {
assertEquals("https://www.coredump.ch/wp-content/uploads/2016/11/logo.png", parsed.logo)
assertEquals("https://www.coredump.ch/", parsed.url.toString())
- assertEquals("Neue Jonastrasse 107, 8640 Rapperswil, Switzerland", parsed.location.address)
- assertEquals(47.2251f, parsed.location.lon)
- assertEquals(8.8339f, parsed.location.lat)
+ assertEquals("Neue Jonastrasse 107, 8640 Rapperswil, Switzerland", parsed.location!!.address)
+ assertEquals(47.2251f, parsed.location!!.lon)
+ assertEquals(8.8339f, parsed.location!!.lat)
assertEquals(false, parsed.state!!.open)
assertEquals(null, parsed.state!!.lastchange)
@@ -96,9 +96,9 @@ class ParserTestKotlin {
assertEquals("https://www.coredump.ch/wp-content/uploads/2016/11/logo.png", parsed.logo)
assertEquals("https://www.coredump.ch/", parsed.url.toString())
- assertEquals("Neue Jonastrasse 107, 8640 Rapperswil, Switzerland", parsed.location.address)
- assertEquals(47.2251f, parsed.location.lon)
- assertEquals(8.8339f, parsed.location.lat)
+ assertEquals("Neue Jonastrasse 107, 8640 Rapperswil, Switzerland", parsed.location!!.address)
+ assertEquals(47.2251f, parsed.location!!.lon)
+ assertEquals(8.8339f, parsed.location!!.lat)
assertEquals(false, parsed.state!!.open)
assertEquals(null, parsed.state!!.lastchange)
@@ -130,9 +130,9 @@ class ParserTestKotlin {
assertEquals("Coredump", parsed.space)
assertEquals("https://www.coredump.ch/wp-content/uploads/2016/11/logo.png", parsed.logo)
assertEquals("https://www.coredump.ch/", parsed.url)
- assertEquals(null, parsed.location.address)
- assertEquals(47.2251f, parsed.location.lon)
- assertEquals(8.8339f, parsed.location.lat)
+ assertEquals(null, parsed.location!!.address)
+ assertEquals(47.2251f, parsed.location!!.lon)
+ assertEquals(8.8339f, parsed.location!!.lat)
@Suppress("DEPRECATION")
assertEquals(emptySet(), parsed.issue_report_channels)
@@ -150,6 +150,89 @@ class ParserTestKotlin {
assertEquals(setOf("14"), parsed.api_compatibility)
}
+ @Test
+ fun testParseV15FromString() {
+ val parsed = parseString("""
+ {
+ "api": "0.13",
+ "api_compatibility": ["14", "15"],
+ "space": "Coredump",
+ "logo": "https://www.coredump.ch/wp-content/uploads/2016/11/logo.png",
+ "url": "https://www.coredump.ch/",
+ "location": {
+ "address": "Neue Jonastrasse 107, 8640 Rapperswil, Switzerland",
+ "lon": 47.2251,
+ "lat": 8.8339,
+ "country_code": "CH",
+ "hint": "Ring bell twice"
+ },
+ "contact": {
+ "email": "vorstand@lists.coredump.ch",
+ "irc": "irc://freenode.net/#coredump",
+ "twitter": "@coredump_ch"
+ },
+ "issue_report_channels": ["email", "twitter"],
+ "state": {
+ "open": false,
+ "message": "Open Mondays from 20:00"
+ },
+ "linked_spaces": [
+ {
+ "endpoint": "https://spaceapi.kabelsalat.ch/",
+ "website": "https://ccc-basel.ch/"
+ }
+ ]
+ }
+ """)
+
+ assertEquals("Coredump", parsed.space)
+ assertEquals("0.13", parsed.api)
+ assertEquals(setOf("14", "15"), parsed.api_compatibility)
+ assertEquals("https://www.coredump.ch/wp-content/uploads/2016/11/logo.png", parsed.logo)
+ assertEquals("https://www.coredump.ch/", parsed.url.toString())
+
+ assertEquals("Neue Jonastrasse 107, 8640 Rapperswil, Switzerland", parsed.location!!.address)
+ assertEquals(47.2251f, parsed.location!!.lon)
+ assertEquals(8.8339f, parsed.location!!.lat)
+ assertEquals("CH", parsed.location!!.country_code)
+ assertEquals("Ring bell twice", parsed.location!!.hint)
+
+ assertEquals(false, parsed.state!!.open)
+ assertEquals(null, parsed.state!!.lastchange)
+ assertEquals("Open Mondays from 20:00", parsed.state!!.message)
+
+ assertEquals("vorstand@lists.coredump.ch", parsed.contact.email)
+ assertEquals("irc://freenode.net/#coredump", parsed.contact.irc)
+ assertEquals("@coredump_ch", parsed.contact.twitter)
+ assertEquals(null, parsed.contact.facebook)
+
+ assertEquals(1, parsed.linked_spaces.size)
+ assertEquals("https://spaceapi.kabelsalat.ch/", parsed.linked_spaces[0].endpoint)
+ assertEquals("https://ccc-basel.ch/", parsed.linked_spaces[0].website)
+
+ @Suppress("DEPRECATION")
+ assertEquals(setOf("email", "twitter"), parsed.issue_report_channels)
+ }
+
+ private val minimalV15Data = """{
+ "api_compatibility": ["15"],
+ "space": "Coredump",
+ "logo": "https://www.coredump.ch/wp-content/uploads/2016/11/logo.png",
+ "url": "https://www.coredump.ch/",
+ "contact": {}
+ }"""
+
+ @Test
+ fun testParseV15Minimal() {
+ val parsed = parseString(minimalV15Data)
+
+ assertEquals(setOf("15"), parsed.api_compatibility)
+ assertEquals("Coredump", parsed.space)
+ assertEquals("https://www.coredump.ch/wp-content/uploads/2016/11/logo.png", parsed.logo)
+ assertEquals("https://www.coredump.ch/", parsed.url)
+ assertEquals(null, parsed.location)
+ }
+
/**
* Regression test for #2.
*/