Upgrade to Pro — share decks privately, control downloads, hide ads and more …

KtorでおうちAPIをリプレースした話

Avatar for yagi2 yagi2
December 18, 2017

 KtorでおうちAPIをリプレースした話

2017/12/18 CA.kt #5 @大阪 LT

Avatar for yagi2

yagi2

December 18, 2017
Tweet

More Decks by yagi2

Other Decks in Programming

Transcript

  1. ͍͋ͭ͝͞ - ࣗݾ঺հ - • ໊લ : ੨༄ थ Itsuki

    AOYAGIʢ23ʣ
 a.k.a ΍͗ʹ͍ • AndroidΞϓϦΤϯδχΞ • Kotlinྺ : ໿൒೥ • Twitter : @yaginier • GitHub etc… : @yagi2 / @yagi21 • ͓͏͍͖ͪͩ͢
  2. ͍͋ͭ͝͞ - ࣗݾ঺հ - • ໊લ : ੨༄ थ Itsuki

    AOYAGIʢ23ʣ
 a.k.a ΍͗ʹ͍ • AndroidΞϓϦΤϯδχΞ • Kotlinྺ : ໿൒೥ • Twitter : @yaginier • GitHub etc… : @yagi2 / @yagi21 • ͓͏͍͖ͪͩ͢
  3. ͓͏ͪϋοΫ - զ͕Ո - ɾRaspberry Piʢॳ୅ʣ ɹˠ ͓͏ͪAPI͕͸͍͑ͯΔʢPHPʣ ɹɹˠ ϒϥ΢β͔ΒHTTPSܦ༝ͯ͠ϖʔδ͔Βୟ͘

    ɹɹˠ ࣗ࡞ͷAndroidΞϓϦ͔ΒϦΫΤετ Ұྫ ɾࣗ୐ͷσεΫτοϓPCͷిݯΛ֎͔ΒೖΕΔ ɾΤΞίϯɺςϨϏ౳ͷ੺֎ઢͰૢ࡞͢ΔՈిͷૢ࡞ ɾϥδΦʢRasPiΛrtmpετϦʔϛϯά࢖ͬͯϥδΦʹ͍ͯͨ͠ʣ
  4. ͓͏ͪϋοΫ - զ͕Ո - ɾRaspberry Piʢॳ୅ʣ ɹˠ ͓͏ͪAPI͕͸͍͑ͯΔʢPHPʣ ɹɹˠ ϒϥ΢β͔ΒHTTPSܦ༝ͯ͠ϖʔδ͔Βୟ͘

    ɹɹˠ ࣗ࡞ͷAndroidΞϓϦ͔ΒϦΫΤετ Ұྫ ɾࣗ୐ͷσεΫτοϓPCͷిݯΛ֎͔ΒೖΕΔ ɾΤΞίϯɺςϨϏ౳ͷ੺֎ઢͰૢ࡞͢ΔՈిͷૢ࡞ ɾϥδΦʢRasPiΛrtmpετϦʔϛϯά࢖ͬͯϥδΦʹ͍ͯͨ͠ʣ
  5. ͓͏ͪϋοΫ - զ͕Ո - ɾRaspberry Piʢॳ୅ʣ ɹˠ ͓͏ͪAPI͕͸͍͑ͯΔʢPHPʣ ɹɹˠ ϒϥ΢β͔ΒHTTPSܦ༝ͯ͠ϖʔδ͔Βୟ͘

    ɹɹˠ ࣗ࡞ͷAndroidΞϓϦ͔ΒϦΫΤετ Ұྫ ɾࣗ୐ͷσεΫτοϓPCͷిݯΛ֎͔ΒೖΕΔ ɾΤΞίϯɺςϨϏ౳ͷ੺֎ઢͰૢ࡞͢ΔՈిͷૢ࡞ ɾϥδΦʢRasPiΛrtmpετϦʔϛϯά࢖ͬͯϥδΦʹ͍ͯͨ͠ʣ ͍ͭ͜ΛKotlinʹॻ͖׵͑Δ
  6. αʔόʔαΠυKotlin ɾSpring Boot ɹҎલKotlin + Spring BootͰJSONΛు͘APIΛ࡞ͬͨ͜ͱ͕͋Δ ɹ ͦͷ࣌ͷϒϩά →

    KotlinͱSpring BootΛ࢖ͬͯαΫοͱୟ͚ΔAPIΛ࡞Δ ɾKotr ɹΊͬͪΌബ͍ ɹ ɹKtor is a framework for quickly creating web applications in Kotlin with minimal effort.
  7. Ktor fun main(args: Array<String>) { embeddedServer(Netty, 8080) { routing {

    get("/") { call.respondText("Hello, world!", ContentType.Text.Html) } } }.start(wait = true) } ɾബ͗ͯ͢README͕୹͍ ɹɹɹɹউखͳΠϝʔδ ɹɹɹɹɹɹɹSpringBoot → Ruby on Rails ɹɹɹɹɹɹɹKtor → Sinatra
  8. Ktor - WoL API - KtorΛ࢖ͬͯɺࣗ୐PCͷిݯΛ֎͔ΒೖΕΔAPIΛॻ͖௚͢ ৽͍͠࢓༷ ɾΫϥΠΞϯτ͸POSTͰର৅ͷϗετ໊Λ౤͛Δ ɹˠ ϗετ໊΍ͦΕʹ४ͣΔ΋ͷʢཧ༝͸ޙड़ʣΛ౤͛Δ

    ɹˠ DB౳αʔόʔଆͰϗετ໊ͱMacΞυϨεΛ͓͍࣋ͬͯͯࢀর ɾαʔόʔ͸ड͚औͬͨΒର৅ʹରͯ͠WoL͢Δ ɹ͔ͤͬ͘ͳͷͰϚδοΫύέοτૹ৴Λ࣮૷͢Δ
  9. Ktor - WoL API - install(Routing) { post("/wol") { val

    name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔͸ύϥϝʔλͰ ɹˠ DBʹ͸Exposed + MySQLΛ࢖༻
  10. Ktor - WoL API - install(Routing) { post("/wol") { val

    name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔͸ύϥϝʔλͰ ɹˠ DBʹ͸Exposed + MySQLΛ࢖༻
  11. Ktor - WoL API - install(Routing) { post("/wol") { val

    name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔͸ύϥϝʔλͰ ɹˠ DBʹ͸Exposed + MySQLΛ࢖༻ object Computers : IntIdTable() { val hostName = varchar("hostname", 50).index() val macAddr = varchar("mac_addr", 50) } class Computer(id: EntityID<Int>) : IntEntity(id) { companion object : IntEntityClass<Computer>(Computers) var hostname by Computers.hostName var macAddr by Computers.macAddr } fun findByHostName(hostName: String?): Computer? { return transaction { Computer.find { Computers.hostName eq hostName }.firstOrNull() } }
  12. Ktor - WoL API - install(Routing) { post("/wol") { val

    name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔͸ύϥϝʔλͰ ɹˠ DBʹ͸Exposed + MySQLΛ࢖༻
  13. Ktor - WoL API - class WakeOnLan(private val macAddress: String)

    { @Throws(IOException::class) fun sendMagicPacket() { val iNetAddress = InetAddress.getByName("255.255.255.255") val magicPacket = getMagicPacket(macAddress) DatagramSocket().send(DatagramPacket(magicPacket, magicPacket.size, iNetAddress, 8080)) } private fun getMagicPacket(macAddress: String): ByteArray { val packet = ByteArray(102) var index = 0 repeat(6) { packet[index++] = 0xFF.toByte() } val macAddressByte = getMacAddressByte(macAddress) repeat(16) { repeat(6) { packet[index++] = macAddressByte[it] } } return packet } private fun getMacAddressByte(macAddress: String): ByteArray = macAddress.split(":").map { Integer.parseInt(it, 16).toByte() }.toByteArray() }
  14. Google Home + IFTTT ໰୊఺ ී௨ʹϓϩάϥϜ͔ΒPOST͢Δͱ͖͸ $ curl --data-urlencode "name=hoge"

    http://api.example.com/wol Google Homeͩͱ”name=hoge”͕ͭΒ͍ ɹˠ ೔ຊޠͰͷΤΠϦΞεΛ෇͚ͯDBͷΧϥϜʹೖΕ͓ͯ͘ ྫʣʮͶ͐ɺGoogle ͏ͪͷ͜ͱΓΛىͯ͜͠ʯ ɹɹˠ name=͜ͱΓ ɹɹˠ DB͔Βʮ͜ͱΓʯͰҰக͢ΔͷΛݕࡧͯ͠΍Δ
  15. Google Home + IFTTT object Computers : IntIdTable() { val

    hostName = varchar("hostname", 50).index() val macAddr = varchar("mac_addr", 50) } class Computer(id: EntityID<Int>) : IntEntity(id) { companion object : IntEntityClass<Computer>(Computers) var hostname by Computers.hostName var macAddr by Computers.macAddr } fun findByHostName(hostName: String?): Computer? { return transaction { Computer.find { Computers.hostName eq hostName }.firstOrNull() } } object Computers : IntIdTable() { val hostName = varchar("hostname", 50).index() val name = varchar("name", 50) val macAddr = varchar("mac_addr", 50) } class Computer(id: EntityID<Int>) : IntEntity(id) { companion object : IntEntityClass<Computer>(Computers) var hostname by Computers.hostName var name by Computers.name var macAddr by Computers.macAddr } fun findByHostName(hostName: String?): Computer? { return transaction { Computer.find { Computers.hostName eq hostName }.firstOrNull() } } fun findByName(name: String?): Computer? { return transaction { Computer.find { Computers.name eq name }.firstOrNull() } }
  16. Google Home + IFTTT transaction { Computer.new { hostname =

    "kotori" name = "͜ͱΓ" macAddr = “FF:FF:FF:FF:FF:FF” } } ͓Ոʹ͋ΔϚγϯΛDBʹೖΕͯ͋͛Δɻ $ curl --data-urlencode "name=kotori" http://api.example.com:/wol ʮͶ͐ɺGoogle ͓͏ͪͷ͜ͱΓΛىͯ͜͠ʯ ✨྆ํڞOK✨

  17. Google Home + IFTTT ஫ҙ఺ ʮͶ͐ɺGoogle ͏ͪͷ͜ͻͳͨΛىͯ͜͠ʯ → ౉ͬͯ͘Δ໊લ͕ʮ͜ ͻͳ

    ͨʯ ʮͶ͐ɺGoogle ͏ͪͷͪΌͪΌΛىͯ͜͠ʯ → ౉ͬͯ͘Δ໊લ͕ʮ஡ʑʯ ղܾࡦ → 1ճࢼͯ͠Կ͕౉ͬͯ͘Δͷ͔ΛݟΔ