From 8455390247edcdfa12b2bf803da2ade6c1d569d5 Mon Sep 17 00:00:00 2001 From: Christian Zufferey Date: Sat, 8 Dec 2018 11:45:57 +0100 Subject: [PATCH] =?UTF-8?q?Modifs=20du=20mega-dojo=20du=207=20d=C3=A9cembr?= =?UTF-8?q?e=202018?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chapeau_led/anthony/a_train3.lua | 66 ++++ LED_RGB_WS2812/chapeau_led/deploy/dir.lua | 15 + LED_RGB_WS2812/chapeau_led/deploy/luatool.py | 358 ++++++++++++++++++ .../chapeau_led/{initz.lua => init.lua} | 0 .../chapeau_led/michael/a_train3.lua | 67 ++++ LED_RGB_WS2812/chapeau_led/michael/boot.lua | 10 + LED_RGB_WS2812/chapeau_led/michael/test.lua | 67 ++++ LED_RGB_WS2812/chapeau_led/toto.lua | 3 + 8 files changed, 586 insertions(+) create mode 100644 LED_RGB_WS2812/chapeau_led/anthony/a_train3.lua create mode 100644 LED_RGB_WS2812/chapeau_led/deploy/dir.lua create mode 100755 LED_RGB_WS2812/chapeau_led/deploy/luatool.py rename LED_RGB_WS2812/chapeau_led/{initz.lua => init.lua} (100%) create mode 100644 LED_RGB_WS2812/chapeau_led/michael/a_train3.lua create mode 100644 LED_RGB_WS2812/chapeau_led/michael/boot.lua create mode 100644 LED_RGB_WS2812/chapeau_led/michael/test.lua create mode 100644 LED_RGB_WS2812/chapeau_led/toto.lua diff --git a/LED_RGB_WS2812/chapeau_led/anthony/a_train3.lua b/LED_RGB_WS2812/chapeau_led/anthony/a_train3.lua new file mode 100644 index 0000000..22bcf6e --- /dev/null +++ b/LED_RGB_WS2812/chapeau_led/anthony/a_train3.lua @@ -0,0 +1,66 @@ +nbleds=36 +train_speed=200 +ws2812.init() +myLedStrip1 = ws2812.newBuffer(nbleds, 3) + +zpower=128 + +function train1_fill() + myLedStrip1:fill(0,0,0) + myLedStrip1:set(1, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(2, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(3, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(4, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(5, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(6, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(7, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(8, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(9, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(10, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(11, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(12, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(13, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(14, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(15, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(16, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(17, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(18, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(19, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(20, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(21, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(22, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(23, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(24, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(25, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(26, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(27, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(28, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(29, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(30, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(31, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(32, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(33, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(34, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(35, math.random(zpower), math.random(zpower), math.random(zpower)) + myLedStrip1:set(36, math.random(zpower), math.random(zpower), math.random(zpower)) +end +function train_write() + ws2812.write(myLedStrip1) +end + +function train_start() + train3timer1=tmr.create() + tmr.alarm(train3timer1, train_speed, tmr.ALARM_AUTO, function() + train1_fill() + train_write() + end) +end +function train_stop() + tmr.unregister(train3timer1) + RGB_clear() +end + + +RGB_clear() +train1_fill() +train_start() diff --git a/LED_RGB_WS2812/chapeau_led/deploy/dir.lua b/LED_RGB_WS2812/chapeau_led/deploy/dir.lua new file mode 100644 index 0000000..8bf9414 --- /dev/null +++ b/LED_RGB_WS2812/chapeau_led/deploy/dir.lua @@ -0,0 +1,15 @@ +-- fonction dir() pour afficher les fichiers dans la flash +print("\n dir.lua zf180826.1019 \n") + +function dir() + print("\n-------------------------------") + l=file.list() i=0 + for k,v in pairs(l) do + i=i+v + print(k..string.rep(" ",19-string.len(k)).." : "..v.." bytes") + end + print("-------------------------------") + print('\nUsed: '..i..' bytes\nusage: dofile("file.lua")\n') +end + +dir() diff --git a/LED_RGB_WS2812/chapeau_led/deploy/luatool.py b/LED_RGB_WS2812/chapeau_led/deploy/luatool.py new file mode 100755 index 0000000..e9db586 --- /dev/null +++ b/LED_RGB_WS2812/chapeau_led/deploy/luatool.py @@ -0,0 +1,358 @@ +#!/usr/bin/env python2 +# +# ESP8266 luatool +# Author e-mail: 4ref0nt@gmail.com +# Site: http://esp8266.ru +# Contributions from: https://github.com/sej7278 +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin +# Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import sys +import serial +from time import sleep +import socket +import argparse +from os.path import basename + + +tqdm_installed = True +try: + from tqdm import tqdm +except ImportError, e: + if e.message == 'No module named tqdm': + tqdm_installed = False + else: + raise + +version = "0.6.4" + + +class TransportError(Exception): + """Custom exception to represent errors with a transport + """ + def __init__(self, message): + self.message = message + + def __str__(self): + return self.message + +class AbstractTransport: + def __init__(self): + raise NotImplementedError('abstract transports cannot be instantiated.') + + def close(self): + raise NotImplementedError('Function not implemented') + + def read(self, length): + raise NotImplementedError('Function not implemented') + + def writeln(self, data, check=1): + raise NotImplementedError('Function not implemented') + + def writer(self, data): + self.writeln("file.writeline([==[" + data + "]==])\r") + + def performcheck(self, expected): + line = '' + char = '' + i = -1 + while char != chr(62): # '>' + char = self.read(1) + if char == '': + raise Exception('No proper answer from MCU') + if char == chr(13) or char == chr(10): # LF or CR + if line != '': + line = line.strip() + if line+'\r' == expected and not args.bar: + sys.stdout.write(" -> ok") + elif line+'\r' != expected: + if line[:4] == "lua:": + sys.stdout.write("\r\n\r\nLua ERROR: %s" % line) + raise Exception('ERROR from Lua interpreter\r\n\r\n') + else: + expected = expected.split("\r")[0] + sys.stdout.write("\r\n\r\nERROR") + sys.stdout.write("\r\n send string : '%s'" % expected) + sys.stdout.write("\r\n expected echo : '%s'" % expected) + sys.stdout.write("\r\n but got answer : '%s'" % line) + sys.stdout.write("\r\n\r\n") + raise Exception('Error sending data to MCU\r\n\r\n') + line = '' + else: + line += char + if char == chr(62) and expected[i] == char: + char = '' + i += 1 + + +class SerialTransport(AbstractTransport): + def __init__(self, port, baud, delay): + self.port = port + self.baud = baud + self.serial = None + self.delay = delay + + try: + self.serial = serial.Serial(port, baud) + except serial.SerialException as e: + raise TransportError(e.strerror) + + self.serial.timeout = 3 + self.serial.interCharTimeout = 3 + + def writeln(self, data, check=1): + if self.serial.inWaiting() > 0: + self.serial.flushInput() + if len(data) > 0 and not args.bar: + sys.stdout.write("\r\n->") + sys.stdout.write(data.split("\r")[0]) + self.serial.write(data) + sleep(self.delay) + if check > 0: + self.performcheck(data) + elif not args.bar: + sys.stdout.write(" -> send without check") + + def read(self, length): + return self.serial.read(length) + + def close(self): + self.serial.flush() + self.serial.close() + + +class TcpSocketTransport(AbstractTransport): + def __init__(self, host, port): + self.host = host + self.port = port + self.socket = None + + try: + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + except socket.error as e: + raise TransportError(e.strerror) + + try: + self.socket.connect((host, port)) + except socket.error as e: + raise TransportError(e.strerror) + # read intro from telnet server (see telnet_srv.lua) + self.socket.recv(50) + + def writeln(self, data, check=1): + if len(data) > 0 and not args.bar: + sys.stdout.write("\r\n->") + sys.stdout.write(data.split("\r")[0]) + self.socket.sendall(data) + if check > 0: + self.performcheck(data) + elif not args.bar: + sys.stdout.write(" -> send without check") + + def read(self, length): + return self.socket.recv(length) + + def close(self): + self.socket.close() + + +def decidetransport(cliargs): + if cliargs.ip: + data = cliargs.ip.split(':') + host = data[0] + if len(data) == 2: + port = int(data[1]) + else: + port = 23 + return TcpSocketTransport(host, port) + else: + return SerialTransport(cliargs.port, cliargs.baud, cliargs.delay) + + +if __name__ == '__main__': + # parse arguments or use defaults + parser = argparse.ArgumentParser(description='ESP8266 Lua script uploader.') + parser.add_argument('-p', '--port', default='/dev/ttyUSB0', help='Device name, default /dev/ttyUSB0') + parser.add_argument('-b', '--baud', default=9600, help='Baudrate, default 9600') + parser.add_argument('-f', '--src', default='main.lua', help='Source file on computer, default main.lua') + parser.add_argument('-t', '--dest', default=None, help='Destination file on MCU, default to source file name') + parser.add_argument('-c', '--compile', action='store_true', help='Compile lua to lc after upload') + parser.add_argument('-r', '--restart', action='store_true', help='Restart MCU after upload') + parser.add_argument('-d', '--dofile', action='store_true', help='Run the Lua script after upload') + parser.add_argument('-v', '--verbose', action='store_true', help="Show progress messages.") + parser.add_argument('-a', '--append', action='store_true', help='Append source file to destination file.') + parser.add_argument('-l', '--list', action='store_true', help='List files on device') + parser.add_argument('-w', '--wipe', action='store_true', help='Delete all lua/lc files on device.') + parser.add_argument('-i', '--id', action='store_true', help='Query the modules chip id.') + parser.add_argument('-e', '--echo', action='store_true', help='Echo output of MCU until script is terminated.') + parser.add_argument('--bar', action='store_true', help='Show a progress bar for uploads instead of printing each line') + parser.add_argument('--delay', default=0.3, help='Delay in seconds between each write.', type=float) + parser.add_argument('--delete', default=None, help='Delete a lua/lc file from device.') + parser.add_argument('--ip', default=None, help='Connect to a telnet server on the device (--ip IP[:port])') + args = parser.parse_args() + + transport = decidetransport(args) + + if args.bar and not tqdm_installed: + sys.stdout.write("You must install the tqdm library to use the bar feature\n") + sys.stdout.write("To install, at the prompt type: \"pip install tqdm\"\n") + sys.exit(0) + + + if args.list: + transport.writeln("local l = file.list();for k,v in pairs(l) do print('name:'..k..', size:'..v)end\r", 0) + while True: + char = transport.read(1) + if char == '' or char == chr(62): + break + sys.stdout.write(char) + sys.exit(0) + + if args.id: + transport.writeln("=node.chipid()\r", 0) + id="" + while True: + char = transport.read(1) + if char == '' or char == chr(62): + break + if char.isdigit(): + id += char + print("\n"+id) + sys.exit(0) + + if args.wipe: + transport.writeln("local l = file.list();for k,v in pairs(l) do print(k)end\r", 0) + file_list = [] + fn = "" + while True: + char = transport.read(1) + if char == '' or char == chr(62): + break + if char not in ['\r', '\n']: + fn += char + else: + if fn: + file_list.append(fn.strip()) + fn = '' + for fn in file_list[1:]: # first line is the list command sent to device + if args.verbose: + sys.stderr.write("Delete file {} from device.\r\n".format(fn)) + transport.writeln("file.remove(\"" + fn + "\")\r") + sys.exit(0) + + if args.delete: + transport.writeln("file.remove(\"" + args.delete + "\")\r") + sys.exit(0) + + if args.dest is None: + args.dest = basename(args.src) + + # open source file for reading + try: + try: + f = open(args.src, "rt") + except: + import os + base_dir = os.path.dirname(os.path.realpath(__file__)) + f = open(os.path.join(base_dir, args.src), "rt") + os.chdir(base_dir) + except: + sys.stderr.write("Could not open input file \"%s\"\n" % args.src) + sys.exit(1) + + # Verify the selected file will not exceed the size of the serial buffer. + # The size of the buffer is 256. This script does not accept files with + # lines longer than 230 characters to have some room for command overhead. + num_lines = 0 + for ln in f: + if len(ln) > 230: + sys.stderr.write("File \"%s\" contains a line with more than 240 " + "characters. This exceeds the size of the serial buffer.\n" + % args.src) + f.close() + sys.exit(1) + num_lines += 1 + + # Go back to the beginning of the file after verifying it has the correct + # line length + f.seek(0) + + # set serial timeout + if args.verbose: + sys.stderr.write("Upload starting\r\n") + + # remove existing file on device + if args.append==False: + if args.verbose: + sys.stderr.write("Stage 1. Deleting old file from flash memory") + transport.writeln("file.open(\"" + args.dest + "\", \"w\")\r") + transport.writeln("file.close()\r") + transport.writeln("file.remove(\"" + args.dest + "\")\r") + else: + if args.verbose: + sys.stderr.write("[SKIPPED] Stage 1. Deleting old file from flash memory [SKIPPED]") + + + # read source file line by line and write to device + if args.verbose: + sys.stderr.write("\r\nStage 2. Creating file in flash memory and write first line") + if args.append: + transport.writeln("file.open(\"" + args.dest + "\", \"a+\")\r") + else: + transport.writeln("file.open(\"" + args.dest + "\", \"w+\")\r") + line = f.readline() + if args.verbose: + sys.stderr.write("\r\nStage 3. Start writing data to flash memory...") + if args.bar: + for i in tqdm(range(0, num_lines)): + transport.writer(line.strip()) + line = f.readline() + else: + while line != '': + transport.writer(line.strip()) + line = f.readline() + + # close both files + f.close() + if args.verbose: + sys.stderr.write("\r\nStage 4. Flush data and closing file") + transport.writeln("file.flush()\r") + transport.writeln("file.close()\r") + + # compile? + if args.compile: + if args.verbose: + sys.stderr.write("\r\nStage 5. Compiling") + transport.writeln("node.compile(\"" + args.dest + "\")\r") + transport.writeln("file.remove(\"" + args.dest + "\")\r") + + # restart or dofile + if args.restart: + transport.writeln("node.restart()\r") + if args.dofile: # never exec if restart=1 + transport.writeln("dofile(\"" + args.dest + "\")\r", 0) + + if args.echo: + if args.verbose: + sys.stderr.write("\r\nEchoing MCU output, press Ctrl-C to exit") + while True: + sys.stdout.write(transport.read(1)) + + # close serial port + transport.close() + + # flush screen + sys.stdout.flush() + sys.stderr.flush() + if not args.bar: + sys.stderr.write("\r\n--->>> All done <<<---\r\n") diff --git a/LED_RGB_WS2812/chapeau_led/initz.lua b/LED_RGB_WS2812/chapeau_led/init.lua similarity index 100% rename from LED_RGB_WS2812/chapeau_led/initz.lua rename to LED_RGB_WS2812/chapeau_led/init.lua diff --git a/LED_RGB_WS2812/chapeau_led/michael/a_train3.lua b/LED_RGB_WS2812/chapeau_led/michael/a_train3.lua new file mode 100644 index 0000000..c917776 --- /dev/null +++ b/LED_RGB_WS2812/chapeau_led/michael/a_train3.lua @@ -0,0 +1,67 @@ +-- Scripts juste pour tester l'effet train +-- tout sur la couleur: https://www.w3schools.com/colors/default.asp +-- roue des couleurs: https://iro.js.org/?ref=oldsite + +print("\n a_train3.lua zf181205.1919 \n") + +nbleds=36 +fade1=0.05 fade2=0.2 fade3=0.4 fade4=1 +R1=255 G1=0 B1=0 +R2=255 G2=0 B2=0 +train_speed=50 +ws2812.init() +myLedStrip = ws2812.newBuffer(nbleds, 16) +myLedStrip1 = ws2812.newBuffer(nbleds, 3) +myLedStrip2 = ws2812.newBuffer(nbleds, 3) + +function RGB_clear() + myLedStrip:fill(0, 0, 0) ws2812.write(myLedStrip) +end + +function train1_fill() + myLedStrip1:fill(0,0,0) + myLedStrip1:set(1, G1*fade1, R1*fade1, B1*fade1) + myLedStrip1:set(2, G1*fade2, R1*fade2, B1*fade2) + myLedStrip1:set(3, G1*fade3, R1*fade3, B1*fade3) + myLedStrip1:set(4, G1*fade4, R1*fade4, B1*fade4) +end + +function train2_fill() + myLedStrip2:fill(0,0,0) + myLedStrip2:set(nbleds, G2*fade1, R2*fade1, B2*fade1) + myLedStrip2:set(nbleds-1, G2*fade2, R2*fade2, B2*fade2) + myLedStrip2:set(nbleds-2, G2*fade3, R2*fade3, B2*fade3) + myLedStrip2:set(nbleds-3, G2*fade4, R2*fade4, B2*fade4) +end + +function train_mix() + myLedStrip:mix(255, myLedStrip1, 255, myLedStrip2) +end + +function train_shift() + myLedStrip1:shift(1, ws2812.SHIFT_CIRCULAR) + myLedStrip2:shift(-1, ws2812.SHIFT_CIRCULAR) +end + +function train_write() + ws2812.write(myLedStrip) +end + +function train_start() + train3timer1=tmr.create() + tmr.alarm(train3timer1, train_speed, tmr.ALARM_AUTO, function() + train_shift() + train_mix() + train_write() + end) +end + +function train_stop() + tmr.unregister(train3timer1) + RGB_clear() +end + +RGB_clear() +train1_fill() +train2_fill() +train_start() diff --git a/LED_RGB_WS2812/chapeau_led/michael/boot.lua b/LED_RGB_WS2812/chapeau_led/michael/boot.lua new file mode 100644 index 0000000..d2e664e --- /dev/null +++ b/LED_RGB_WS2812/chapeau_led/michael/boot.lua @@ -0,0 +1,10 @@ +-- Scripts � charger apr�s le boot pour d�marrer son appli + +print("\n boot.lua 07.12.18 1634\n") +f= "wifi_ap_stop.lua" if file.exists(f) then dofile(f) end +f= "wifi_cli_conf.lua" if file.exists(f) then dofile(f) end +f= "wifi_cli_start.lua" if file.exists(f) then dofile(f) end +f= "web_ide2.lua" if file.exists(f) then dofile(f) end +f= "az_init_led.lua" if file.exists(f) then dofile(f) end +f= "webleds.lua" if file.exists(f) then dofile(f) end +f= "test.lua" if file.exists(f) then dofile(f) end diff --git a/LED_RGB_WS2812/chapeau_led/michael/test.lua b/LED_RGB_WS2812/chapeau_led/michael/test.lua new file mode 100644 index 0000000..a59c330 --- /dev/null +++ b/LED_RGB_WS2812/chapeau_led/michael/test.lua @@ -0,0 +1,67 @@ +-- Scripts juste pour tester l'effet train +-- tout sur la couleur: https://www.w3schools.com/colors/default.asp +-- roue des couleurs: https://iro.js.org/?ref=oldsite + +print("\n test.lua zf181207.1634 \n") + +nbleds=36 +fade1=0.05 fade2=0.2 fade3=0.4 fade4=1 +R1=255 G1=0 B1=0 +R2=0 G2=0 B2=255 +train_speed=50 +ws2812.init() +myLedStrip = ws2812.newBuffer(nbleds, 3) +myLedStrip1 = ws2812.newBuffer(nbleds, 3) +myLedStrip2 = ws2812.newBuffer(nbleds, 3) + +function RGB_clear() + myLedStrip:fill(0, 0, 0) ws2812.write(myLedStrip) +end + +function train1_fill() + myLedStrip1:fill(0,0,0) + myLedStrip1:set(1, G1*fade1, R1*fade1, B1*fade1) + myLedStrip1:set(2, G1*fade2, R1*fade2, B1*fade2) + myLedStrip1:set(3, G1*fade3, R1*fade3, B1*fade3) + myLedStrip1:set(4, G1*fade4, R1*fade4, B1*fade4) +end + +function train2_fill() + myLedStrip2:fill(0,0,0) + myLedStrip2:set(nbleds, G2*fade1, R2*fade1, B2*fade1) + myLedStrip2:set(nbleds-1, G2*fade2, R2*fade2, B2*fade2) + myLedStrip2:set(nbleds-2, G2*fade3, R2*fade3, B2*fade3) + myLedStrip2:set(nbleds-3, G2*fade4, R2*fade4, B2*fade4) +end + +function train_mix() + myLedStrip:mix(255, myLedStrip1, 255, myLedStrip2) +end + +function train_shift() + myLedStrip1:shift(1, ws2812.SHIFT_CIRCULAR) + myLedStrip2:shift(-1, ws2812.SHIFT_CIRCULAR) +end + +function train_write() + ws2812.write(myLedStrip) +end + +function train_start() + train3timer1=tmr.create() + tmr.alarm(train3timer1, train_speed, tmr.ALARM_AUTO, function() + train_shift() + train_mix() + train_write() + end) +end + +function train_stop() + tmr.unregister(train3timer1) + RGB_clear() +end + +RGB_clear() +train1_fill() +train2_fill() +train_start() diff --git a/LED_RGB_WS2812/chapeau_led/toto.lua b/LED_RGB_WS2812/chapeau_led/toto.lua new file mode 100644 index 0000000..e477839 --- /dev/null +++ b/LED_RGB_WS2812/chapeau_led/toto.lua @@ -0,0 +1,3 @@ +a=3 +b=5 +print(a*b)