PLCNEXT#PyPlcnextRscを使ってみよう_2_変数読み書き編

今回の記事ではPyPlcnextRscのAPIを使用し、AXC F 2152 CPUの変数(単体変数・配列・構造体)を読み書きする操作をサンプルコード付きで説明します。よろしくおねがいします。このAPIは非常に便利なので、よかったら試してみてください。

Reference Link

https://pyplcnextrsc.readthedocs.io/en/latest/index.html

PLCNEXT#Install pip
PLCNEXT#SSL Certificate problem cerificate is not yet valid
PLCNEXT#PyPlcnextRscを使ってみよう_1

The Access Path

PyPlcnextRscを使用しPLCNEXTの変数を読み取りのに、変数のAccess Pathを明確にする必要があります。例えば今回のExampleではまずPLCnext(2)をクリックします。

自分のCyclic TaskにはOB11といLocal Programがあります。

Component nameのところにArp.Plc.Eclrという名称があり、それはAccess Pathの一部になります。

Implementation-1 Read Variable

Implementation-1ではPLCNEXT Runtime内にあるいくつかの変数をリクエスト分けて読み取ってみます。ExampleにはBOOL TypeのMyBoolDatat・16Bitの整数MyInt・文字列 TypeのMyStringがTargetです。

Script Example

こちらはScriptです。

MyBoolDataのアクセスPathは:Arp.Plc.EclrOB11/MyBoolData、

MyStringのアクセスPathは:Arp.Plc.EclrOB11/OB11.MyString、

MyIntのアクセスPathは:Arp.Plc.EclrOB11/OB11.MyInt、になります。

そしてReadSingle() Methodを使用し変数の現在値を読み取ります。

from PyPlcnextRsc import Device, ConsoleSupplierExample , RscVariant
from PyPlcnextRsc.Arp.Device.Interface.Services import IDeviceInfoService,IDeviceStatusService
from PyPlcnextRsc.Arp.Plc.Gds.Services import IDataAccessService,WriteItem
from PyPlcnextRsc.common.tag_type import IecType

PLCNEXTIPADDRESS=’127.0.0.1′
PLCNEXTBASICPATH=’Arp.Plc.Eclr/’

with Device(PLCNEXTIPADDRESS, secureInfoSupplier=ConsoleSupplierExample) as device:
device_info_service = IDeviceInfoService(device)
device_status_service = IDeviceStatusService(device)
info_items = [
    “General.ArticleName”,
    “General.ArticleNumber”,
    “General.SerialNumber”,
    “General.Firmware.Version”,
    “General.Hardware.Version”,
    “Interfaces.Ethernet.1.0.Mac”
]
status_items = [
    “Status.Cpu.0.Load.Percent”,
    “Status.Memory.Usage.Percent”,
    “Status.ProgramMemoryIEC.Usage.Percent”,
    “Status.DataMemoryIEC.Usage.Percent”,
    “Status.Board.Temperature.Centigrade”,
    “Status.Board.Temperature.Centigrade”,
    “Status.Board.Humidity”
]
for identifier, result in zip(info_items, device_info_service.GetItems(info_items)):
    print(identifier.rjust(40) + ” : ” + str(result.GetValue()))
for identifier, result in zip(status_items, device_status_service.GetItems(status_items)):
    print(identifier.rjust(40) + ” : ” + str(result.GetValue()))
data_access_service=IDataAccessService(device)
Bool_port_name=PLCNEXTBASICPATH+”OB11.MyBoolData”
String_port_name=PLCNEXTBASICPATH+”OB11.MyString”
int_port_name=PLCNEXTBASICPATH+”OB11.MyInt”

value=data_access_service.ReadSingle(Bool_port_name).Value.GetValue()
print(value)
print(data_access_service.ReadSingle(String_port_name).Value.GetValue())
print(data_access_service.ReadSingle(int_port_name).Value.GetValue())
data_access_service.WriteSingle(WriteItem(Bool_port_name,RscVariant.of(True)))
data_access_service.WriteSingle(WriteItem(String_port_name,RscVariant.of(‘abcdef’)))

Result

Done!変数の現在値が取りました。

Implementation-2 Try to write other variable

次はWriteItem() Methodを使用しInt変数を書き込んでみます。

data_access_service.WriteSingle(WriteItem(int_port_name,RscVariant.of(1234)))

ですが、エラーがReturnされています。

Traceback (most recent call last):
File “/opt/plcnext/RoboDKTesting/myapps.py”, line 58, in <module>
    data_access_service.WriteSingle(WriteItem(int_port_name,RscVariant.of(1234)))
File “/opt/plcnext/.local/lib/python3.10/site-packages/PyPlcnextRsc/common/objects/rsc_variant.py”, line 74, in of
    raise InvalidOperationException(“Use __init__ to create RscVariant with its’ RscType instead !”)
PyPlcnextRsc.common.exceptions.InvalidOperationException: Use __init__ to create RscVariant with its’ RscType instead !

Why?

こちらのLINKからWriteItem() MethodのSource Codeが見れます↓

https://pyplcnextrsc.readthedocs.io/en/latest/_modules/PyPlcnextRsc/common/objects/rsc_variant.html#RscVariant.of

中にBool・Strucutre・String以外にすべてのData TyoeもExceptionになります。どうやら書き込みのTargetに明確なData Typeを指定する必要があるようです。例えば整数12を書き込むだけではその12は16Bit?32Bit?Sign?Unsignなどが曖昧なので、受け付けません。

Implementation-3 Array Operation

先程のImplemenationでは整数を書き込めなかったんですね。ですが、配列のINTなら問題ありません。次はそのMethodなどを紹介します。

Create Array

配列のData Typeを作成し、Runtime内でLocal変数を宣言します。

Script Example

今回はDataTypeStore.fromString()関数を使います。()のパラメータはアクセスしたい変数のデータタイプをそのままPLCNEXTからCOPYしてもいいし、もう一つテキストから読む関数もあり、あの関数を使っても構いません。

TypeStore = DataTypeStore.fromString(
“””
TYPE

    MyIntArray : ARRAY[0..10] OF INT;

    END_TYPE
    “””
    )

TypeStore.NewSchemaInstance()から変数のInstanceを宣言します。

MyIntArrayData = TypeStore.NewSchemaInstance(“MyIntArray”)

最後は配列の読み書きを行います。

read_item = data_access_service.Read((MyArray_port_name,))[0]
print(read_item)
print(read_item.Value)

data_access_service.Write((WriteItem(MyArray_port_name, RscVariant.of(MyIntArrayData)),))

こちらはScriptの全体です。

from PyPlcnextRsc import Device, ConsoleSupplierExample , RscVariant
from PyPlcnextRsc.Arp.Device.Interface.Services import IDeviceInfoService,IDeviceStatusService
from PyPlcnextRsc.Arp.Plc.Gds.Services import IDataAccessService,WriteItem
from PyPlcnextRsc.common.tag_type import IecType
from PyPlcnextRsc.tools import DataTypeStore

PLCNEXTIPADDRESS=’127.0.0.1′
PLCNEXTBASICPATH=’Arp.Plc.Eclr/’

TypeStore = DataTypeStore.fromString(
“””
TYPE

    MyIntArray : ARRAY[0..10] OF INT;

    END_TYPE
    “””
    )

with Device(PLCNEXTIPADDRESS, secureInfoSupplier=ConsoleSupplierExample) as device:
device_info_service = IDeviceInfoService(device)
device_status_service = IDeviceStatusService(device)
info_items = [
    “General.ArticleName”,
    “General.ArticleNumber”,
    “General.SerialNumber”,
    “General.Firmware.Version”,
    “General.Hardware.Version”,
    “Interfaces.Ethernet.1.0.Mac”
]
status_items = [
    “Status.Cpu.0.Load.Percent”,
    “Status.Memory.Usage.Percent”,
    “Status.ProgramMemoryIEC.Usage.Percent”,
    “Status.DataMemoryIEC.Usage.Percent”,
    “Status.Board.Temperature.Centigrade”,
    “Status.Board.Temperature.Centigrade”,
    “Status.Board.Humidity”
]
for identifier, result in zip(info_items, device_info_service.GetItems(info_items)):
    print(identifier.rjust(40) + ” : ” + str(result.GetValue()))
for identifier, result in zip(status_items, device_status_service.GetItems(status_items)):
    print(identifier.rjust(40) + ” : ” + str(result.GetValue()))

    #Create Data access services
data_access_service=IDataAccessService(device)

#Create Port
Bool_port_name=PLCNEXTBASICPATH+”OB11.MyBoolData”
String_port_name=PLCNEXTBASICPATH+”OB11.MyString”
int_port_name=PLCNEXTBASICPATH+”OB11.MyInt”
MyArray_port_name=PLCNEXTBASICPATH+”OB11.MyIntArray1″

#Print the values
print(data_access_service.ReadSingle(Bool_port_name).Value.GetValue())
print(data_access_service.ReadSingle(String_port_name).Value.GetValue())
print(data_access_service.ReadSingle(int_port_name).Value.GetValue())
data_access_service.WriteSingle(WriteItem(Bool_port_name,RscVariant.of(True)))
data_access_service.WriteSingle(WriteItem(String_port_name,RscVariant.of(‘abcdef’)))

#Array operation
MyIntArrayData = TypeStore.NewSchemaInstance(“MyIntArray”)
MyIntArrayData[:] = [i * 2 for i in range(11)]
read_item = data_access_service.Read((MyArray_port_name,))[0]
print(read_item)
print(read_item.Value)

data_access_service.Write((WriteItem(MyArray_port_name, RscVariant.of(MyIntArrayData)),))

Result

Terminal上でScriptを実行すると、データはエラーなく読み書きできました。

PLCNEXTからも結果の確認ができます。

Implementation-4 Structure

次は少し構造体にアクセスしてみます。PLCNEXTのプロジェクトに構造体を宣言してください。今回の例ではMyStructData_1で、INT・BOOL・Real・LReal Typeの要素が含まれています。

Create Structure

PLCNEXTの中にSTRUCTのデータタイプを定義し、Runtime内でLocal変数を宣言します。

Script Example

DataTypeStore.fromString()はPLCNEXTで定義した構造体をそのまま貼り付ければよです。

TypeStore = DataTypeStore.fromString(
“””
TYPE
    MyIntArray : ARRAY[0..10] OF INT;
   
    MyStructData_1 : STRUCT
        Field1_INT  : INT;
        Field2_BOOL : BOOL;
        Field3_Real : REAL;
        Field4_LReal :LREAL;
    END_STRUCT
END_TYPE
    “””
    )

次は変数のInstanceを宣言します。

MyTestStruct_port_name=PLCNEXTBASICPATH+”OB11.MyTestStruct”

data_access_service.Read()とread_struct_item.Valueから変数の現在値を取得します。

#
MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”)
read_struct_item = data_access_service.Read((MyTestStruct_port_name,))[0]
print(‘———————‘)
print(read_struct_item.Value)

こちらはScriptの全体です。

from PyPlcnextRsc import Device, ConsoleSupplierExample , RscVariant
from PyPlcnextRsc.Arp.Device.Interface.Services import IDeviceInfoService,IDeviceStatusService
from PyPlcnextRsc.Arp.Plc.Gds.Services import IDataAccessService,WriteItem
from PyPlcnextRsc.common.tag_type import IecType
from PyPlcnextRsc.tools import DataTypeStore

IPADDRESS=’192.168.1.194′
PORT=20500
ROBOTNAME=’Fanuc_Robot’
PLCNEXTIPADDRESS=’127.0.0.1′
PLCNEXTBASICPATH=’Arp.Plc.Eclr/’

TypeStore = DataTypeStore.fromString(
“””
TYPE
    MyIntArray : ARRAY[0..10] OF INT;
   
    MyStructData_1 : STRUCT
        Field1_INT  : INT;
        Field2_BOOL : BOOL;
        Field3_Real : REAL;
        Field4_LReal :LREAL;
    END_STRUCT
END_TYPE
    “””
    )

with Device(PLCNEXTIPADDRESS, secureInfoSupplier=ConsoleSupplierExample) as device:
device_info_service = IDeviceInfoService(device)
device_status_service = IDeviceStatusService(device)
info_items = [
    “General.ArticleName”,
    “General.ArticleNumber”,
    “General.SerialNumber”,
    “General.Firmware.Version”,
    “General.Hardware.Version”,
    “Interfaces.Ethernet.1.0.Mac”
]
status_items = [
    “Status.Cpu.0.Load.Percent”,
    “Status.Memory.Usage.Percent”,
    “Status.ProgramMemoryIEC.Usage.Percent”,
    “Status.DataMemoryIEC.Usage.Percent”,
    “Status.Board.Temperature.Centigrade”,
    “Status.Board.Temperature.Centigrade”,
    “Status.Board.Humidity”
]
for identifier, result in zip(info_items, device_info_service.GetItems(info_items)):
    print(identifier.rjust(40) + ” : ” + str(result.GetValue()))
for identifier, result in zip(status_items, device_status_service.GetItems(status_items)):
    print(identifier.rjust(40) + ” : ” + str(result.GetValue()))

    #Create Data access services
data_access_service=IDataAccessService(device)

#Create Port
Bool_port_name=PLCNEXTBASICPATH+”OB11.MyBoolData”
String_port_name=PLCNEXTBASICPATH+”OB11.MyString”
int_port_name=PLCNEXTBASICPATH+”OB11.MyInt”
MyArray_port_name=PLCNEXTBASICPATH+”OB11.MyIntArray1″
MyTestStruct_port_name=PLCNEXTBASICPATH+”OB11.MyTestStruct”

#Print the values
print(data_access_service.ReadSingle(Bool_port_name).Value.GetValue())
print(data_access_service.ReadSingle(String_port_name).Value.GetValue())
print(data_access_service.ReadSingle(int_port_name).Value.GetValue())
data_access_service.WriteSingle(WriteItem(Bool_port_name,RscVariant.of(True)))
data_access_service.WriteSingle(WriteItem(String_port_name,RscVariant.of(‘abcdef’)))

#Array operation
MyIntArrayData = TypeStore.NewSchemaInstance(“MyIntArray”)
MyIntArrayData[:] = [i * 2 for i in range(11)]
read_item = data_access_service.Read((MyArray_port_name,))[0]
print(read_item)
print(read_item.Value)

data_access_service.Write((WriteItem(MyArray_port_name, RscVariant.of(MyIntArrayData)),))

#
MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”)
read_struct_item = data_access_service.Read((MyTestStruct_port_name,))[0]
print(‘———————‘)
print(read_struct_item.Value)

Result

PLCNEXTからも結果の確認ができます。

Terminal上でScriptを実行すると、データはエラーなく読みました。

Implementation-5 Write the structure

次は構造体の変数に現在値を書き込みます。

#
MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”)
MyTestStructData.Field1_INT=459
MyTestStructData.Field2_BOOL=True
MyTestStructData.Field3_Real=3.14
MyTestStructData.Field4_LReal=991.41155
read_struct_item = data_access_service.Read((MyTestStruct_port_name,))[0]
print(‘———————‘)
print(read_struct_item.Value)

Script Example

構造体変数のInstanceにPLCNEXTと定義した変数名とデータタイプをあわせて適当な値を書き込みます。

#
MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”)
MyTestStructData.Field1_INT=459
MyTestStructData.Field2_BOOL=True
MyTestStructData.Field3_Real=3.14
MyTestStructData.Field4_LReal=991.41155

data_access_service.Write()を使用し書き込みのリクエストを送信します。

data_access_service.Write((WriteItem(MyTestStruct_port_name, RscVariant.of(MyTestStructData)),))

こちらはScriptの全体です。

from PyPlcnextRsc import Device, ConsoleSupplierExample , RscVariant
from PyPlcnextRsc.Arp.Device.Interface.Services import IDeviceInfoService,IDeviceStatusService
from PyPlcnextRsc.Arp.Plc.Gds.Services import IDataAccessService,WriteItem
from PyPlcnextRsc.common.tag_type import IecType
from PyPlcnextRsc.tools import DataTypeStore


PLCNEXTIPADDRESS=’127.0.0.1′
PLCNEXTBASICPATH=’Arp.Plc.Eclr/’

TypeStore = DataTypeStore.fromString(
“””
TYPE
    MyIntArray : ARRAY[0..10] OF INT;
   
    MyStructData_1 : STRUCT
        Field1_INT  : INT;
        Field2_BOOL : BOOL;
        Field3_Real : REAL;
        Field4_LReal :LREAL;
    END_STRUCT
END_TYPE
    “””
    )



with Device(PLCNEXTIPADDRESS, secureInfoSupplier=ConsoleSupplierExample) as device:
device_info_service = IDeviceInfoService(device)
device_status_service = IDeviceStatusService(device)
info_items = [
    “General.ArticleName”,
    “General.ArticleNumber”,
    “General.SerialNumber”,
    “General.Firmware.Version”,
    “General.Hardware.Version”,
    “Interfaces.Ethernet.1.0.Mac”
]
status_items = [
    “Status.Cpu.0.Load.Percent”,
    “Status.Memory.Usage.Percent”,
    “Status.ProgramMemoryIEC.Usage.Percent”,
    “Status.DataMemoryIEC.Usage.Percent”,
    “Status.Board.Temperature.Centigrade”,
    “Status.Board.Temperature.Centigrade”,
    “Status.Board.Humidity”
]
for identifier, result in zip(info_items, device_info_service.GetItems(info_items)):
    print(identifier.rjust(40) + ” : ” + str(result.GetValue()))
for identifier, result in zip(status_items, device_status_service.GetItems(status_items)):
    print(identifier.rjust(40) + ” : ” + str(result.GetValue()))

    #Create Data access services
data_access_service=IDataAccessService(device)

#Create Port
Bool_port_name=PLCNEXTBASICPATH+”OB11.MyBoolData”
String_port_name=PLCNEXTBASICPATH+”OB11.MyString”
int_port_name=PLCNEXTBASICPATH+”OB11.MyInt”
MyArray_port_name=PLCNEXTBASICPATH+”OB11.MyIntArray1″
MyTestStruct_port_name=PLCNEXTBASICPATH+”OB11.MyTestStruct”

#Print the values
print(data_access_service.ReadSingle(Bool_port_name).Value.GetValue())
print(data_access_service.ReadSingle(String_port_name).Value.GetValue())
print(data_access_service.ReadSingle(int_port_name).Value.GetValue())
data_access_service.WriteSingle(WriteItem(Bool_port_name,RscVariant.of(True)))
data_access_service.WriteSingle(WriteItem(String_port_name,RscVariant.of(‘abcdef’)))

#Array operation
MyIntArrayData = TypeStore.NewSchemaInstance(“MyIntArray”)
MyIntArrayData[:] = [i * 2 for i in range(11)]
read_item = data_access_service.Read((MyArray_port_name,))[0]
print(read_item)
print(read_item.Value)

data_access_service.Write((WriteItem(MyArray_port_name, RscVariant.of(MyIntArrayData)),))

#
MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”)
MyTestStructData.Field1_INT=459
MyTestStructData.Field2_BOOL=True
MyTestStructData.Field3_Real=3.14
MyTestStructData.Field4_LReal=991.41155
read_struct_item = data_access_service.Read((MyTestStruct_port_name,))[0]
print(‘———————‘)
print(read_struct_item.Value)

data_access_service.Write((WriteItem(MyTestStruct_port_name, RscVariant.of(MyTestStructData)),))

Result

Terminal上でScriptを実行すると、データはエラーなく読み書きできました。

Implementation-6 Encode the RsvVariant to Python object

最後はRsvVariantをPython Scriptで使用できるObjectに変換します。

Script Example

こちらのScriptからRsvVariantをPython Objectに変換します。

complexStruct_Received = TypeStore.ReceiveAsSchemaInstance(“MyStructData_1”, read_struct_item.Value)
print(“Field1_INT is:”+str(complexStruct_Received.Field1_INT))
print(“Field2_BOOL is “+str(complexStruct_Received.Field2_BOOL))
print(“Field3_Real is “+str(complexStruct_Received.Field3_Real))
print(“Field4_LReal is “+str(complexStruct_Received.Field4_LReal))

こちらはScriptの全体です。

from PyPlcnextRsc import Device, ConsoleSupplierExample , RscVariant
from PyPlcnextRsc.Arp.Device.Interface.Services import IDeviceInfoService,IDeviceStatusService
from PyPlcnextRsc.Arp.Plc.Gds.Services import IDataAccessService,WriteItem
from PyPlcnextRsc.common.tag_type import IecType
from PyPlcnextRsc.tools import DataTypeStore


PLCNEXTIPADDRESS=’127.0.0.1′
PLCNEXTBASICPATH=’Arp.Plc.Eclr/’

TypeStore = DataTypeStore.fromString(
“””
TYPE
    MyIntArray : ARRAY[0..10] OF INT;
   
    MyStructData_1 : STRUCT
        Field1_INT  : INT;
        Field2_BOOL : BOOL;
        Field3_Real : REAL;
        Field4_LReal :LREAL;
    END_STRUCT
END_TYPE
    “””
    )



with Device(PLCNEXTIPADDRESS, secureInfoSupplier=ConsoleSupplierExample) as device:
device_info_service = IDeviceInfoService(device)
device_status_service = IDeviceStatusService(device)
info_items = [
    “General.ArticleName”,
    “General.ArticleNumber”,
    “General.SerialNumber”,
    “General.Firmware.Version”,
    “General.Hardware.Version”,
    “Interfaces.Ethernet.1.0.Mac”
]
status_items = [
    “Status.Cpu.0.Load.Percent”,
    “Status.Memory.Usage.Percent”,
    “Status.ProgramMemoryIEC.Usage.Percent”,
    “Status.DataMemoryIEC.Usage.Percent”,
    “Status.Board.Temperature.Centigrade”,
    “Status.Board.Temperature.Centigrade”,
    “Status.Board.Humidity”
]
for identifier, result in zip(info_items, device_info_service.GetItems(info_items)):
    print(identifier.rjust(40) + ” : ” + str(result.GetValue()))
for identifier, result in zip(status_items, device_status_service.GetItems(status_items)):
    print(identifier.rjust(40) + ” : ” + str(result.GetValue()))

    #Create Data access services
data_access_service=IDataAccessService(device)

#Create Port
Bool_port_name=PLCNEXTBASICPATH+”OB11.MyBoolData”
String_port_name=PLCNEXTBASICPATH+”OB11.MyString”
int_port_name=PLCNEXTBASICPATH+”OB11.MyInt”
MyArray_port_name=PLCNEXTBASICPATH+”OB11.MyIntArray1″
MyTestStruct_port_name=PLCNEXTBASICPATH+”OB11.MyTestStruct”

#Print the values
print(data_access_service.ReadSingle(Bool_port_name).Value.GetValue())
print(data_access_service.ReadSingle(String_port_name).Value.GetValue())
print(data_access_service.ReadSingle(int_port_name).Value.GetValue())
data_access_service.WriteSingle(WriteItem(Bool_port_name,RscVariant.of(True)))
data_access_service.WriteSingle(WriteItem(String_port_name,RscVariant.of(‘abcdef’)))

#Array operation
MyIntArrayData = TypeStore.NewSchemaInstance(“MyIntArray”)
MyIntArrayData[:] = [i * 2 for i in range(11)]
read_item = data_access_service.Read((MyArray_port_name,))[0]
print(read_item)
print(read_item.Value)

data_access_service.Write((WriteItem(MyArray_port_name, RscVariant.of(MyIntArrayData)),))

#
MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”)
MyTestStructData.Field1_INT=459
MyTestStructData.Field2_BOOL=True
MyTestStructData.Field3_Real=3.14
MyTestStructData.Field4_LReal=991.41155
read_struct_item = data_access_service.Read((MyTestStruct_port_name,))[0]
print(‘———————‘)
print(read_struct_item.Value)

data_access_service.Write((WriteItem(MyTestStruct_port_name, RscVariant.of(MyTestStructData)),))
complexStruct_Received = TypeStore.ReceiveAsSchemaInstance(“MyStructData_1”, read_struct_item.Value)
print(“Field1_INT is:”+str(complexStruct_Received.Field1_INT))
print(“Field2_BOOL is “+str(complexStruct_Received.Field2_BOOL))
print(“Field3_Real is “+str(complexStruct_Received.Field3_Real))
print(“Field4_LReal is “+str(complexStruct_Received.Field4_LReal))

Result

CPU内部変数の現在値がPLCNEXT Engineeringソフトから確認できます。

同じの値が読みましたね!

Footer_Basic

Please Support some devices for my blog

Amazon Gift List

Find ME

Twitter:@3threes2
Email:soup01threes*gmail.com (* to @)
YoutubeChannel:https://www.youtube.com/channel/UCQ3CHGAIXZAbeOC_9mjQiWQ

シェアする

  • このエントリーをはてなブックマークに追加

フォローする