iOS機とESP32とのBLEテキスト通信モジュールを考えてみた

#この情報は時代遅れですよのご報告
　残念ながらPythonista3でのBLE通信は2023年4月末のUpdateより動きません。
　※動かない状況：BLE受信はできますがBLE送信はエラーがでて送信不可※
　現在はSwift Playgroundにて同様のプログラムを作ろうと奮闘中です・・


 ArduinoManagerに期待を裏切られたのはESP32編で書きましたが、
今回はiOS機で初めて開発することにしました。でも個人の私で用意出来るのは
普段使いのWindowsPCとiPad Proなので、Pythonista3は自然な流れになります。

#実行に必要なリソース
　　ESP32とArduinoIDE開発環境（別述
　　iOS機とPythonista3アプリ

#機能
　　ESP32側はSerial通信と同じような使い方がしたいので、私がよく使う
　　Serial通信のメソッドだけサポートしていました。
　　iOS側も似たような感じのメソッドを用意する事にしました。
　　available
　　read
　　SendChars
　　＝＝あまり厳密なテストは行っていませんので、意図しない制約があると思います＝＝

#使い方
　　ソフトを起動すると簡素な画面が現れます
![IMG_7039.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255936/89f27e2f-e17c-2245-ad46-4df0eeb8b9c6.png)
　「SelectBLE」を押して接続するBLE機器を選択します。

![IMG_7041.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255936/2ff91989-b9e7-f232-aa79-9dade00fd7b4.png)
　BLE機器のID一覧が表示されるので対象の機器を選択します。
　※表示が無い場合は一度終了して再表示してみてください。

![IMG_7042.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255936/864dd133-c438-32c6-b880-ddca8ba36da2.png)
　機器を選択すると接続するIDが表示されます。
　「Send」ボタンでメッセージを送信します。
　Receiveが受信メッセージを表示しています。


#BLE_SERVER_NAMEとSERVICE_UUIDとCHAR_UUID
　　うまく説明できないので他の資料を確認してください。


メインプログラムです。
　iCloudのPythonista3フォルダにコピーすれば登録できます。
```py:selectBLE.py:
import ui
import cb
import dialogs

TM_BLE_SERVER_NAME ='ESP32'
TM_SERVICE_UUID = 'FFAA'
TM_CHAR_UUID    = '0001'
TM_BUFFER = 40

class BLESeralDelegate(object):
	def __init__(self):
		self.peripheral = None
		self.buffer = bytearray(TM_BUFFER)
		self.bufferwrite = 0
		self.bufferread  = 0
		
	def did_discover_peripheral(self, p):
		global peripheralList, titleList
		print(('+++discoverd : %s %s' % (p.name, p.uuid) ))
		if p.name!=None and not self.peripheral:
			peripheralList.append( p )
			titleList.append( p.uuid )
			
	def did_connect_peripheral(self, p):
		print(('***connected : %s' % p.name))
		p.discover_services()
		v['label1'].text = 'connected'
		
	def did_fail_to_connect_peripheral(self,p,error):
		print('fail to connect')
		v['label1'].text = 'fail to connect'
		
	def did_disconnect_peripheral(self, p, error):
		print(('disconnected, error: %s' % (error,)))
		self.peripheral = None
		self.data_characteristics = None
		cb.scan_for_peripherals()
		
	def did_discover_services(self, p, error):
		print('service search')
		for s in p.services:
			if TM_SERVICE_UUID in s.uuid:
				print('turget uuid found')
				p.discover_characteristics(s)
				
	def did_discover_characteristics(self,s, error):
		if TM_SERVICE_UUID in s.uuid:
			for c in  s.characteristics:
				if TM_CHAR_UUID in c.uuid:
					self.peripheral.set_notify_value(c, True)
					self.data_characteristics = c
					self.peripheral.write_characteristic_value(c, chr(0), True)
					cb.stop_scan()

	def did_update_value(self, c, error):
		if TM_CHAR_UUID==c.uuid:
			for ch in c.value:
				self.buffer[ self.bufferwrite ]=int(ch)
				self.bufferwrite = self.bufferwrite + 1
				if self.bufferwrite == TM_BUFFER :
					self.bufferwrite = 0
	
	def use(self):
		if self.peripheral and self.data_characteristics :
			return True
		else:
			return False
	
	def available(self):
		if self.bufferwrite == self.bufferread :
			return False
		return True
	
	def read(self):
		ret = self.buffer[ self.bufferread ]		
		if self.bufferread == (TM_BUFFER - 1):
			self.bufferread = 0
		else:
			self.bufferread = self.bufferread + 1
		return ret
							
	def send_chars(self, message):
		if self.peripheral and self.data_characteristics :
			self.peripheral.write_characteristic_value(self.data_characteristics, message+chr(0), True)
	
def onSelect(sender):
	global BLEserial, peripheralList, titleList
	uucv = dialogs.list_dialog(title='BLE list', items=titleList)
	for p in peripheralList:
		if p.uuid==uucv:
			BLEserial.peripheral = p
			cb.connect_peripheral(p)
			v['labelBLE'].text = p.uuid

def onSend(sender):
	global BLEserial,count
	BLEserial.send_chars('BLE Message:'+str(count))
	count=count+1

v = ui.load_view('selectBLE.pyui')
wi = ui.NavigationView(v)
wi.height = 960
wi.width = 680
wi.name = 'BLE serial'
wi.present('sheet')

peripheralList = list()
titleList=list()
count=1
BLEserial = BLESeralDelegate()
cb.set_central_delegate(BLEserial)
cb.scan_for_peripherals()
buffer = bytearray(0)
loop_program = True
try:
	while loop_program:
		if BLEserial.available() :
			num = BLEserial.read()
			if num != 0 :
				buffer.append(num)
			else:
				response = buffer.decode()
				buffer = bytearray(0)
				print(response)
				v['labelReceive'].text = response
					
except KeyboardInterrupt:
	cb.reset()
```


こちらは画面の定義です。
　iCloudのPythonista3フォルダにコピーすれば登録できます。
```pyui:selectBLE.pyui:
[
  {
    "nodes" : [
      {
        "nodes" : [

        ],
        "frame" : "{{24, 17}, {130, 46}}",
        "class" : "Button",
        "attributes" : {
          "border_width" : 1,
          "action" : "onSelect",
          "frame" : "{{230, 254}, {80, 32}}",
          "title" : "SelectBLE",
          "uuid" : "3ADCC5B5-52AA-4EF8-B500-FC69B804296F",
          "class" : "Button",
          "corner_radius" : 1,
          "name" : "button1",
          "font_size" : 15
        },
        "selected" : false
      },
      {
        "nodes" : [

        ],
        "frame" : "{{24, 81}, {501, 32}}",
        "class" : "Label",
        "attributes" : {
          "font_size" : 18,
          "frame" : "{{195, 254}, {150, 32}}",
          "uuid" : "D6795BDD-20DE-473D-9598-676BE8EDCE52",
          "class" : "Label",
          "alignment" : "left",
          "text" : "",
          "name" : "labelBLE",
          "font_name" : "<System>"
        },
        "selected" : false
      },
      {
        "nodes" : [

        ],
        "frame" : "{{20, 121}, {107, 32}}",
        "class" : "Button",
        "attributes" : {
          "border_width" : 1,
          "action" : "onSend",
          "frame" : "{{472, 368}, {80, 32}}",
          "title" : "Send",
          "uuid" : "5FE9A7C8-1E3C-4B40-97B3-F331FD5538D3",
          "class" : "Button",
          "corner_radius" : 1,
          "name" : "buttonSend",
          "font_size" : 15
        },
        "selected" : false
      },
      {
        "nodes" : [

        ],
        "frame" : "{{261, 31}, {324, 32}}",
        "class" : "Label",
        "attributes" : {
          "name" : "label1",
          "frame" : "{{437, 368}, {150, 32}}",
          "uuid" : "341C9782-7020-41BE-AA3A-6450AC11C484",
          "class" : "Label",
          "alignment" : "left",
          "text" : "",
          "font_size" : 18,
          "font_name" : "<System>"
        },
        "selected" : false
      },
      {
        "nodes" : [

        ],
        "frame" : "{{24, 161}, {103, 32}}",
        "class" : "Label",
        "attributes" : {
          "name" : "label2",
          "frame" : "{{437, 368}, {150, 32}}",
          "uuid" : "955F8864-E2C7-4BEB-88BA-28E591217826",
          "class" : "Label",
          "alignment" : "left",
          "text" : "Receive",
          "font_size" : 18,
          "font_name" : "<System>"
        },
        "selected" : false
      },
      {
        "nodes" : [

        ],
        "frame" : "{{169, 31}, {84, 32}}",
        "class" : "Label",
        "attributes" : {
          "font_size" : 18,
          "frame" : "{{437, 368}, {150, 32}}",
          "uuid" : "789A55EA-66EC-49DA-89FA-5AFBB5795181",
          "class" : "Label",
          "alignment" : "left",
          "text" : "Status",
          "name" : "label3",
          "font_name" : "<System>"
        },
        "selected" : false
      },
      {
        "nodes" : [

        ],
        "frame" : "{{135, 161}, {426, 32}}",
        "class" : "Label",
        "attributes" : {
          "font_size" : 18,
          "frame" : "{{437, 368}, {150, 32}}",
          "uuid" : "B66B74A6-F7EC-4E30-9722-8B2B535BD745",
          "class" : "Label",
          "alignment" : "left",
          "text" : "",
          "name" : "labelReceive",
          "font_name" : "<System>"
        },
        "selected" : true
      }
    ],
    "frame" : "{{0, 0}, {1024, 768}}",
    "class" : "View",
    "attributes" : {
      "background_color" : "RGBA(1.000000,1.000000,1.000000,1.000000)",
      "enabled" : true,
      "tint_color" : "RGBA(0.000000,0.478000,1.000000,1.000000)",
      "border_color" : "RGBA(0.000000,0.000000,0.000000,1.000000)",
      "name" : "",
      "flex" : ""
    },
    "selected" : false
  }
]
```

あとがき
　　これで一応ESP32とiOS機の通信が出来るようになりました。
　本当はAndroidでもBLE通信出来れば良かったのですが、AndroidのBLE通信に関して
　僕が理解できる情報が見当たりません、誰かWebでソースコード上げてくれると良い
　のだけど・・・。　あとAndroidStudioで多画面のソフト作成が己のスキルの低さ
　故に思う様にいかないので悶々としています。
　最近調べなおしたらAndroidでのBLE通信を説明してくれているサイトがありますね。
　説明して下さる方に感謝しつつ、今度はAndroid用通信モジュールを挑戦したいです。


　どなたか岡山でオッサン加入可能なそんな集まり誘ってくれませんか？　（ぷ