-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
169 changed files
with
2,450 additions
and
2,145 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,34 @@ | ||
package nebulosa.api | ||
|
||
import com.github.rvesse.airline.SingleCommand | ||
import com.sun.jna.Platform | ||
import nebulosa.time.SystemClock | ||
import org.springframework.boot.runApplication | ||
import java.nio.file.Path | ||
import java.time.LocalDate | ||
import java.time.format.DateTimeFormatter | ||
import java.util.* | ||
import javax.swing.filechooser.FileSystemView | ||
import kotlin.io.path.Path | ||
import kotlin.io.path.createDirectories | ||
import kotlin.io.path.deleteIfExists | ||
import kotlin.io.path.exists | ||
import kotlin.io.path.listDirectoryEntries | ||
|
||
const val APP_DIR_KEY = "app.dir" | ||
|
||
fun initAppDirectory(): Path { | ||
val appPath = when { | ||
Platform.isLinux() -> Path.of(System.getProperty("user.home"), ".nebulosa") | ||
Platform.isWindows() -> Path.of(FileSystemView.getFileSystemView().defaultDirectory.path, "Nebulosa") | ||
Platform.isLinux() -> Path(System.getProperty("user.home"), ".nebulosa") | ||
Platform.isWindows() -> Path(FileSystemView.getFileSystemView().defaultDirectory.path, "Nebulosa") | ||
else -> throw IllegalStateException("unsupported operating system") | ||
} | ||
|
||
appPath.createDirectories() | ||
System.setProperty("app.dir", "$appPath") | ||
return appPath | ||
} | ||
|
||
private fun Path.clearLogIfPastDays(days: Long = 7L) { | ||
if (exists()) { | ||
val pastDays = LocalDate.now(SystemClock).minusDays(days) | ||
|
||
for (entry in listDirectoryEntries("nebulosa-*.log")) { | ||
val logDate = entry.fileName.toString() | ||
.replace("nebulosa-", "") | ||
.replace(".log", "") | ||
.let { runCatching { LocalDate.parse(it, DateTimeFormatter.ISO_LOCAL_DATE) }.getOrNull() } | ||
?: continue | ||
|
||
if (pastDays.isAfter(logDate)) { | ||
entry.deleteIfExists() | ||
} | ||
} | ||
} | ||
.createDirectories() | ||
.also { System.setProperty(APP_DIR_KEY, "$it") } | ||
} | ||
|
||
fun main(args: Array<String>) { | ||
with(initAppDirectory()) { | ||
Path.of("$this", "logs").createDirectories().clearLogIfPastDays() | ||
Path.of("$this", "data").createDirectories().also { System.setProperty("DATA_PATH", "$it") } | ||
} | ||
initAppDirectory() | ||
|
||
// Sets default locale to en_US. | ||
Locale.setDefault(Locale.ENGLISH) | ||
|
||
// Run the Spring Boot application. | ||
runApplication<Nebulosa>(*args) | ||
val parser = SingleCommand.singleCommand(Nebulosa::class.java) | ||
val nebulosa = parser.parse(*args) | ||
nebulosa.run() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,81 @@ | ||
package nebulosa.api | ||
|
||
import com.fasterxml.jackson.databind.DeserializationFeature | ||
import com.fasterxml.jackson.databind.SerializationFeature | ||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule | ||
import com.fasterxml.jackson.module.kotlin.jsonMapper | ||
import com.github.rvesse.airline.annotations.Command | ||
import com.github.rvesse.airline.annotations.Option | ||
import io.javalin.Javalin | ||
import io.javalin.json.JavalinJackson | ||
import nebulosa.api.atlas.Location | ||
import nebulosa.api.beans.modules.DeviceModule | ||
import nebulosa.api.inject.* | ||
import nebulosa.json.PathModule | ||
import nebulosa.log.loggerFor | ||
import org.springframework.boot.autoconfigure.SpringBootApplication | ||
import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent | ||
import org.springframework.context.event.EventListener | ||
import org.koin.core.context.startKoin | ||
import java.util.concurrent.ConcurrentHashMap | ||
|
||
@SpringBootApplication | ||
class Nebulosa { | ||
@Command(name = "nebulosa") | ||
class Nebulosa : Runnable, AutoCloseable { | ||
|
||
@EventListener | ||
private fun onServletWebServerInitializedEvent(event: ServletWebServerInitializedEvent) { | ||
LOG.info("server is started at port: ${event.webServer.port}") | ||
@Option(name = ["-h", "--host"]) | ||
private var host = "0.0.0.0" | ||
|
||
@Option(name = ["-p", "--port"]) | ||
private var port = 0 | ||
|
||
private lateinit var app: Javalin | ||
|
||
override fun run() { | ||
// Run the server. | ||
app = Javalin.create { config -> | ||
config.showJavalinBanner = false | ||
// JACKSON | ||
config.jsonMapper(JavalinJackson(OBJECT_MAPPER)) | ||
// CORS | ||
config.bundledPlugins.enableCors { cors -> | ||
cors.addRule { | ||
it.anyHost() | ||
it.exposeHeader("X-Image-Info") | ||
} | ||
} | ||
}.start(host, port) | ||
|
||
koinApp.modules(appModule(app)) | ||
koinApp.modules(objectMapperModule(OBJECT_MAPPER)) | ||
koinApp.modules(servicesModule()) | ||
koinApp.modules(controllersModule()) | ||
startKoin(koinApp) | ||
|
||
LOG.info("server is started at port: {}", app.port()) | ||
} | ||
|
||
override fun close() { | ||
app.stop() | ||
} | ||
|
||
private data object LocationConverter : (String) -> Location? { | ||
|
||
private val CACHED_LOCATION = ConcurrentHashMap<String, Location>(4) | ||
|
||
override fun invoke(value: String): Location? { | ||
return if (value.isBlank()) null | ||
else CACHED_LOCATION.computeIfAbsent(value) { OBJECT_MAPPER.readValue(value, Location::class.java) } | ||
} | ||
} | ||
|
||
companion object { | ||
|
||
@JvmStatic private val LOG = loggerFor<Nebulosa>() | ||
|
||
@JvmStatic private val OBJECT_MAPPER = jsonMapper { | ||
addModule(JavaTimeModule()) | ||
addModule(PathModule()) | ||
addModule(DeviceModule()) | ||
disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) | ||
enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) | ||
disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) | ||
} | ||
} | ||
} |
77 changes: 45 additions & 32 deletions
77
api/src/main/kotlin/nebulosa/api/alignment/polar/PolarAlignmentController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,72 @@ | ||
package nebulosa.api.alignment.polar | ||
|
||
import nebulosa.api.alignment.polar.darv.DARVEvent | ||
import io.javalin.Javalin | ||
import io.javalin.http.Context | ||
import io.javalin.http.bodyAsClass | ||
import nebulosa.api.alignment.polar.darv.DARVStartRequest | ||
import nebulosa.api.alignment.polar.tppa.TPPAEvent | ||
import nebulosa.api.alignment.polar.tppa.TPPAStartRequest | ||
import nebulosa.indi.device.camera.Camera | ||
import nebulosa.indi.device.guider.GuideOutput | ||
import nebulosa.indi.device.mount.Mount | ||
import org.springframework.web.bind.annotation.* | ||
import nebulosa.api.connection.ConnectionService | ||
import nebulosa.api.javalin.notNull | ||
import nebulosa.api.javalin.valid | ||
|
||
@RestController | ||
@RequestMapping("polar-alignment") | ||
class PolarAlignmentController( | ||
app: Javalin, | ||
private val polarAlignmentService: PolarAlignmentService, | ||
private val connectionService: ConnectionService, | ||
) { | ||
|
||
@PutMapping("darv/{camera}/{guideOutput}/start") | ||
fun darvStart( | ||
camera: Camera, guideOutput: GuideOutput, | ||
@RequestBody body: DARVStartRequest, | ||
) = polarAlignmentService.darvStart(camera, guideOutput, body) | ||
init { | ||
app.put("polar-alignment/darv/{camera}/{guideOutput}/start", ::darvStart) | ||
app.put("polar-alignment/darv/{camera}/stop", ::darvStop) | ||
app.get("polar-alignment/darv/{camera}/status", ::darvStatus) | ||
app.put("polar-alignment/tppa/{camera}/{mount}/start", ::tppaStart) | ||
app.put("polar-alignment/tppa/{camera}/stop", ::tppaStop) | ||
app.put("polar-alignment/tppa/{camera}/pause", ::tppaPause) | ||
app.put("polar-alignment/tppa/{camera}/unpause", ::tppaUnpause) | ||
app.get("polar-alignment/tppa/{camera}/status", ::tppaStatus) | ||
} | ||
|
||
private fun darvStart(ctx: Context) { | ||
val camera = connectionService.camera(ctx.pathParam("camera")).notNull() | ||
val guideOutput = connectionService.guideOutput(ctx.pathParam("guideOutput")).notNull() | ||
val body = ctx.bodyAsClass<DARVStartRequest>().valid() | ||
polarAlignmentService.darvStart(camera, guideOutput, body) | ||
} | ||
|
||
@PutMapping("darv/{camera}/stop") | ||
fun darvStop(camera: Camera) { | ||
private fun darvStop(ctx: Context) { | ||
val camera = connectionService.camera(ctx.pathParam("camera")) ?: return | ||
polarAlignmentService.darvStop(camera) | ||
} | ||
|
||
@GetMapping("darv/{camera}/status") | ||
fun darvStatus(camera: Camera): DARVEvent? { | ||
return polarAlignmentService.darvStatus(camera) | ||
private fun darvStatus(ctx: Context) { | ||
val camera = connectionService.camera(ctx.pathParam("camera")).notNull() | ||
polarAlignmentService.darvStatus(camera)?.also(ctx::json) | ||
} | ||
|
||
@PutMapping("tppa/{camera}/{mount}/start") | ||
fun tppaStart( | ||
camera: Camera, mount: Mount, | ||
@RequestBody body: TPPAStartRequest, | ||
) = polarAlignmentService.tppaStart(camera, mount, body) | ||
private fun tppaStart(ctx: Context) { | ||
val camera = connectionService.camera(ctx.pathParam("camera")).notNull() | ||
val mount = connectionService.mount(ctx.pathParam("mount")).notNull() | ||
val body = ctx.bodyAsClass<TPPAStartRequest>().valid() | ||
polarAlignmentService.tppaStart(camera, mount, body) | ||
} | ||
|
||
@PutMapping("tppa/{camera}/stop") | ||
fun tppaStop(camera: Camera) { | ||
private fun tppaStop(ctx: Context) { | ||
val camera = connectionService.camera(ctx.pathParam("camera")) ?: return | ||
polarAlignmentService.tppaStop(camera) | ||
} | ||
|
||
@PutMapping("tppa/{camera}/pause") | ||
fun tppaPause(camera: Camera) { | ||
private fun tppaPause(ctx: Context) { | ||
val camera = connectionService.camera(ctx.pathParam("camera")) ?: return | ||
polarAlignmentService.tppaPause(camera) | ||
} | ||
|
||
@PutMapping("tppa/{camera}/unpause") | ||
fun tppaUnpause(camera: Camera) { | ||
private fun tppaUnpause(ctx: Context) { | ||
val camera = connectionService.camera(ctx.pathParam("camera")) ?: return | ||
polarAlignmentService.tppaUnpause(camera) | ||
} | ||
|
||
@GetMapping("tppa/{camera}/status") | ||
fun tppaStatus(camera: Camera): TPPAEvent? { | ||
return polarAlignmentService.tppaStatus(camera) | ||
private fun tppaStatus(ctx: Context) { | ||
val camera = connectionService.camera(ctx.pathParam("camera")).notNull() | ||
polarAlignmentService.tppaStatus(camera)?.also(ctx::json) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.