@@ -3,6 +3,8 @@ package ai.ancf.lmos.wot.binding.websocket
33import ai.ancf.lmos.wot.JsonMapper
44import ai.ancf.lmos.wot.Servient
55import ai.ancf.lmos.wot.content.ContentManager
6+ import ai.ancf.lmos.wot.protocol.LMOSContext
7+ import ai.ancf.lmos.wot.protocol.LMOS_PROTOCOL_NAME
68import ai.ancf.lmos.wot.thing.ExposedThing
79import ai.ancf.lmos.wot.thing.ThingDescription
810import ai.ancf.lmos.wot.thing.form.Form
@@ -18,16 +20,22 @@ import io.ktor.http.*
1820import io.ktor.serialization.jackson.*
1921import io.ktor.server.application.*
2022import io.ktor.server.engine.*
23+ import io.ktor.server.metrics.micrometer.*
2124import io.ktor.server.netty.*
2225import io.ktor.server.plugins.calllogging.*
2326import io.ktor.server.plugins.contentnegotiation.*
2427import io.ktor.server.routing.*
2528import io.ktor.server.websocket.*
2629import io.ktor.util.reflect.*
2730import io.ktor.websocket.*
31+ import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics
32+ import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics
33+ import io.micrometer.core.instrument.binder.system.ProcessorMetrics
2834import org.slf4j.LoggerFactory
2935import java.util.*
3036
37+ private const val SUB_PROTOCOL_MEDIA_TYPE = " application/json"
38+
3139class WebSocketProtocolServer (
3240 private val wait : Boolean = false ,
3341 private val bindHost : String = " 0.0.0.0" ,
@@ -95,9 +103,9 @@ class WebSocketProtocolServer(
95103 // Create a single form that includes all operations and the subprotocol
96104 val form = Form (
97105 href = href,
98- contentType = " application/json " ,
106+ contentType = SUB_PROTOCOL_MEDIA_TYPE ,
99107 op = operations,
100- subprotocol = " webthingprotocol "
108+ subprotocol = LMOS_PROTOCOL_NAME
101109 )
102110
103111 property.forms + = form
@@ -113,14 +121,14 @@ class WebSocketProtocolServer(
113121 // Create a form for invoking the action
114122 val form = Form (
115123 href = href,
116- contentType = " application/json " ,
124+ contentType = SUB_PROTOCOL_MEDIA_TYPE ,
117125 op = listOf (Operation .INVOKE_ACTION ), // Operation type specific to actions
118- subprotocol = " webthingprotocol " // Specific subprotocol for actions
126+ subprotocol = LMOS_PROTOCOL_NAME // Specific subprotocol for actions
119127 )
120128
121129 // Add the form to the action's forms
122130 action.forms + = form
123- log.debug(" Assign '{}' with subprotocol '{}' to Action '{}'" , href, " webthingprotocol " , name)
131+ log.debug(" Assign '{}' with subprotocol '{}' to Action '{}'" , href, LMOS_PROTOCOL_NAME , name)
124132 }
125133 }
126134
@@ -132,14 +140,14 @@ class WebSocketProtocolServer(
132140 // Create a form for subscribing to the event
133141 val form = Form (
134142 href = href,
135- contentType = " application/json " ,
136- subprotocol = " webthingprotocol " ,
143+ contentType = SUB_PROTOCOL_MEDIA_TYPE ,
144+ subprotocol = LMOS_PROTOCOL_NAME ,
137145 op = listOf (Operation .SUBSCRIBE_EVENT , Operation .UNSUBSCRIBE_EVENT ) // Operation type specific to events
138146 )
139147
140148 // Add the form to the event's forms
141149 event.forms + = form
142- log.debug(" Assign '{}' with subprotocol '{}' to Event '{}'" , href, " webthingprotocol " , name)
150+ log.debug(" Assign '{}' with subprotocol '{}' to Event '{}'" , href, LMOS_PROTOCOL_NAME , name)
143151 }
144152 }
145153}
@@ -159,6 +167,13 @@ fun Application.setupRoutingWithWebSockets(servient: Servient) {
159167 configure(DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES , false )
160168 }
161169 }
170+ install(MicrometerMetrics ) {
171+ meterBinders = listOf (
172+ JvmMemoryMetrics (),
173+ JvmGcMetrics (),
174+ ProcessorMetrics ()
175+ )
176+ }
162177 install(WebSockets ) {
163178 contentConverter = JacksonWebsocketContentConverter (JsonMapper .instance)
164179 }
@@ -438,94 +453,94 @@ private fun createUnsupportedMessageType(thingId: String, correlationId : String
438453 return ErrorMessage (
439454 thingId = thingId,
440455 correlationId = correlationId,
441- type = " https://w3c.github.io/web-thing-protocol /errors#unsupported-message-type" ,
456+ type = " ${ LMOSContext .url} /errors#unsupported-message-type" ,
442457 title = " Unsupported Message Type" ,
443458 status = " 400" ,
444459 detail = " Unsupported message type" ,
445- instance = " https://mythingserver.com /errors/${UUID .randomUUID()} "
460+ instance = " ${ LMOSContext .url} /errors/${UUID .randomUUID()} "
446461 )
447462}
448463
449464private fun createPropertyIsReadOnly (thingId : String , correlationId : String , propertyName : String? ): ErrorMessage {
450465 return ErrorMessage (
451466 thingId = thingId,
452467 correlationId = correlationId,
453- type = " https://w3c.github.io/web-thing-protocol /errors#operation-not-allowed" ,
468+ type = " ${ LMOSContext .url} /errors#operation-not-allowed" ,
454469 title = " Property Read-Only" ,
455470 status = " 405" ,
456471 detail = " Property '$propertyName ' is read-only." ,
457- instance = " https://mythingserver.com /errors/${UUID .randomUUID()} "
472+ instance = " ${ LMOSContext .url} /errors/${UUID .randomUUID()} "
458473 )
459474}
460475
461476private fun createPropertyIsWriteOnly (thingId : String , correlationId : String , propertyName : String? ): ErrorMessage {
462477 return ErrorMessage (
463478 thingId = thingId,
464479 correlationId = correlationId,
465- type = " https://w3c.github.io/web-thing-protocol /errors#operation-not-allowed" ,
480+ type = " ${ LMOSContext .url} /errors#operation-not-allowed" ,
466481 title = " Property is write-only" ,
467482 status = " 405" ,
468483 detail = " Property '$propertyName ' is write-only." ,
469- instance = " https://mythingserver.com /errors/${UUID .randomUUID()} "
484+ instance = " ${ LMOSContext .url} /errors/${UUID .randomUUID()} "
470485 )
471486}
472487
473488private fun createThingNotFound (thingId : String , correlationId : String ): ErrorMessage {
474489 return ErrorMessage (
475490 thingId = thingId,
476491 correlationId = correlationId,
477- type = " https://w3c.github.io/web-thing-protocol /errors#not-found" ,
492+ type = " ${ LMOSContext .url} /errors#not-found" ,
478493 title = " Thing Not Found" ,
479494 status = " 404" ,
480495 detail = " Thing with ID '$thingId ' not found." ,
481- instance = " https://mythingserver.com /errors/${UUID .randomUUID()} "
496+ instance = " ${ LMOSContext .url} /errors/${UUID .randomUUID()} "
482497 )
483498}
484499
485500private fun createInternalServerError (thingId : String , correlationId : String , exceptionMessage : String? ): ErrorMessage {
486501 return ErrorMessage (
487502 thingId = thingId,
488503 correlationId = correlationId,
489- type = " https://w3c.github.io/web-thing-protocol /errors#internal-server-error" ,
504+ type = " ${ LMOSContext .url} /errors#internal-server-error" ,
490505 title = " Internal Server Error" ,
491506 status = " 500" ,
492- detail = " Error reading property : $exceptionMessage " ,
493- instance = " https://mythingserver.com /errors/${UUID .randomUUID()} "
507+ detail = " Internal Server Error : $exceptionMessage " ,
508+ instance = " ${ LMOSContext .url} /errors/${UUID .randomUUID()} "
494509 )
495510}
496511
497512private fun createPropertyNotFound (thingId : String , correlationId : String , propertyName : String? ): ErrorMessage {
498513 return ErrorMessage (
499514 thingId = thingId,
500515 correlationId = correlationId,
501- type = " https://w3c.github.io/web-thing-protocol /errors#not-found" ,
516+ type = " ${ LMOSContext .url} /errors#not-found" ,
502517 title = " Property Not Found" ,
503518 status = " 404" ,
504519 detail = " Property '$propertyName ' not found." ,
505- instance = " https://mythingserver.com /errors/${UUID .randomUUID()} "
520+ instance = " ${ LMOSContext .url} /errors/${UUID .randomUUID()} "
506521 )
507522}
508523
509524private fun createEventNotFound (thingId : String , correlationId : String , eventName : String? ): ErrorMessage {
510525 return ErrorMessage (
511526 thingId = thingId,
512527 correlationId = correlationId,
513- type = " https://w3c.github.io/web-thing-protocol /errors#not-found" ,
528+ type = " ${ LMOSContext .url} /errors#not-found" ,
514529 title = " Event Not Found" ,
515530 status = " 404" ,
516531 detail = " Event '$eventName ' not found." ,
517- instance = " https://mythingserver.com /errors/${UUID .randomUUID()} "
532+ instance = " ${ LMOSContext .url} /errors/${UUID .randomUUID()} "
518533 )
519534}
520535
521536private fun createActionNotFound (thingId : String , correlationId : String , actionName : String? ): ErrorMessage {
522537 return ErrorMessage (
523538 thingId = thingId,
524539 correlationId = correlationId,
525- type = " https://w3c.github.io/web-thing-protocol /errors#not-found" ,
540+ type = " ${ LMOSContext .url} /errors#not-found" ,
526541 title = " Action Not Found" ,
527542 status = " 404" ,
528543 detail = " Action '$actionName ' not found." ,
529- instance = " https://mythingserver.com /errors/${UUID .randomUUID()} "
544+ instance = " ${ LMOSContext .url} /errors/${UUID .randomUUID()} "
530545 )
531546}
0 commit comments