2323package animatedledstrip.server
2424
2525import animatedledstrip.communication.decodeJson
26- import animatedledstrip.communication.toUTF8String
2726import animatedledstrip.leds.animationmanagement.AnimationToRunParams
2827import animatedledstrip.leds.animationmanagement.RunningAnimationParams
2928import animatedledstrip.leds.animationmanagement.startAnimation
@@ -32,11 +31,11 @@ import animatedledstrip.leds.locationmanagement.Location
3231import animatedledstrip.leds.stripmanagement.LEDStrip
3332import animatedledstrip.leds.stripmanagement.NativeLEDStrip
3433import animatedledstrip.leds.stripmanagement.StripInfo
35- import co.touchlab.kermit.Logger
36- import kotlinx.coroutines.*
34+ import animatedledstrip.utils.Logger
35+ import kotlinx.coroutines.CoroutineScope
36+ import kotlinx.coroutines.Dispatchers
37+ import kotlinx.coroutines.launch
3738import java.io.File
38- import java.io.FileInputStream
39- import java.io.FileNotFoundException
4039import java.io.FileOutputStream
4140import java.nio.file.Files
4241import java.nio.file.Paths
@@ -50,6 +49,9 @@ class AnimatedLEDStripServer<T : NativeLEDStrip>(
5049 ledClass : KClass <T >,
5150 internal val pixelLocations : List <Location >? = null ,
5251) {
52+ private val logger = Logger .withTag(" LED Server" )
53+
54+ private val fileOpsScope = CoroutineScope (EmptyCoroutineContext )
5355
5456 /* * Is the server running */
5557 internal var running: Boolean = false
@@ -110,82 +112,76 @@ class AnimatedLEDStripServer<T : NativeLEDStrip>(
110112 }
111113
112114 internal fun savePersistentAnimation (newAnim : RunningAnimationParams ) {
113- val scope = CoroutineScope (EmptyCoroutineContext )
114- scope.launch(Dispatchers .IO ) {
115+ fileOpsScope.launch(Dispatchers .IO ) {
115116 FileOutputStream (" $persistentAnimationDirectory /${newAnim.fileName} " ).apply {
116117 write(newAnim.sourceParams.json())
117118 close()
118119 }
119120 }
120- scope.cancel()
121121 }
122122
123123 internal fun deletePersistentAnimation (anim : RunningAnimationParams ) {
124124 if (File (" $persistentAnimationDirectory /${anim.fileName} " ).exists())
125- Files .delete(Paths .get(" $persistentAnimationDirectory /${anim.fileName} " ))
125+ fileOpsScope.launch(Dispatchers .IO ) {
126+ Files .delete(Paths .get(" $persistentAnimationDirectory /${anim.fileName} " ))
127+ }
126128 }
127129
128130 internal fun loadPersistentAnimations () {
129131 val dir = File (persistentAnimationDirectory)
130- val scope = CoroutineScope (EmptyCoroutineContext )
131132 when {
132- ! dir.exists() -> dir.mkdirs()
133- ! dir.isDirectory -> Logger .w(" $persistentAnimationDirectory should be a directory" )
134- else -> scope .launch {
135- File (persistentAnimationDirectory) .walk().forEach {
133+ ! dir.exists() -> fileOpsScope.launch( Dispatchers . IO ) { dir.mkdirs() }
134+ ! dir.isDirectory -> logger .w(" $persistentAnimationDirectory should be a directory" )
135+ else -> fileOpsScope .launch( Dispatchers . IO ) {
136+ dir .walk().forEach {
136137 if (! it.isDirectory && it.name.endsWith(" .json" ))
137138 try {
138- FileInputStream (it).apply {
139- val obj = readAllBytes().toUTF8String().decodeJson() as AnimationToRunParams
140- leds.animationManager.startAnimation(obj, obj.id)
141- close()
142- }
143- } catch (_: FileNotFoundException ) {
139+ val obj = it.readText().decodeJson() as AnimationToRunParams
140+ leds.animationManager.startAnimation(obj, obj.id)
141+ } catch (e: Exception ) {
142+ logger.w(" Failed to decode ${it.name} : $e " )
144143 }
145144 }
146145 }
147146 }
148- scope.cancel()
149147 }
150148
151149 fun addSavedAnimation (newAnim : AnimationToRunParams ) {
152- Logger .i(newAnim.toString() )
150+ logger .i(" Saved ${ newAnim.id} : $newAnim " )
153151 savedAnimations[newAnim.id] = newAnim
154- FileOutputStream (" $savedAnimationDirectory /${newAnim.fileName} " ).apply {
155- write(newAnim.json())
156- close()
152+ fileOpsScope.launch(Dispatchers .IO ) {
153+ FileOutputStream (" $savedAnimationDirectory /${newAnim.fileName} " ).apply {
154+ write(newAnim.json())
155+ close()
156+ }
157157 }
158158 }
159159
160160 fun deleteSavedAnimation (id : String ) {
161161 savedAnimations.remove(id)
162162 if (File (" $savedAnimationDirectory /$id .json" ).exists())
163- Files .delete(Paths .get(" $savedAnimationDirectory /$id .json" ))
163+ fileOpsScope.launch(Dispatchers .IO ) {
164+ Files .delete(Paths .get(" $savedAnimationDirectory /$id .json" ))
165+ }
164166 }
165167
166168 internal fun loadSavedAnimations () {
167169 val dir = File (savedAnimationDirectory)
168- val scope = CoroutineScope (EmptyCoroutineContext )
169170 when {
170- ! dir.exists() -> dir.mkdirs()
171- ! dir.isDirectory -> Logger .w(" $savedAnimationDirectory should be a directory" )
172- else -> scope .launch {
173- File (savedAnimationDirectory) .walk().forEach {
171+ ! dir.exists() -> fileOpsScope.launch( Dispatchers . IO ) { dir.mkdirs() }
172+ ! dir.isDirectory -> logger .w(" $savedAnimationDirectory should be a directory" )
173+ else -> fileOpsScope .launch( Dispatchers . IO ) {
174+ dir .walk().forEach {
174175 if (! it.isDirectory && it.name.endsWith(" .json" ))
175176 try {
176- FileInputStream (it).apply {
177- val obj = readAllBytes().toUTF8String().decodeJson() as AnimationToRunParams
178- savedAnimations[obj.id] = obj
179- close()
180- }
181- } catch (_: FileNotFoundException ) {
177+ val obj = it.readText().decodeJson() as AnimationToRunParams
178+ savedAnimations[obj.id] = obj
182179 } catch (e: Exception ) {
183- Logger .e (" Failed to decode ${it.name} : $e " )
180+ logger.w (" Failed to decode ${it.name} : $e " )
184181 }
185182 }
186183 }
187184 }
188- scope.cancel()
189185 }
190186
191187 val httpServer = httpServer(this )
0 commit comments