Rebble Clay: New way to configure your Pebble and Core apps and faces!

You know Pebble Clay, but have you heard of Rebble Clay? The new revived pebble-package helps you configure your apps on all platforms, including Flint! Help us test the new package by replacing pebble-clay in your package.json with @rebble/clay. https://www.npmjs.com/package/@rebble/clay

11 Likes

Any other differences between pebble-clay and @rebble/clay other than Flint support? And any plans for further changes?

Not right now, the most important parts for now were to make sure it builds and works on all the existing platforms. I do have some improvements in mind, if you find anything you want for yourself, let me know, I might be able to include it in the future releases!

3 Likes

Wonderful to see!

I’m trying this out on my moto maker watchface - it will build when I s/"pebble-clay": "^1.0.4"/"@rebble/clay": "^1.0.4", but fails to build when I add ”flint” to my ”targetPlatforms”. Here is my build output:

pebble clean && pebble build
lavender@orpheus /m/c/U/p/O/D/p/MotoMakerFace (master) [1]> pebble clean && pebble build
'distclean' finished successfully (0.013s)

up to date, audited 2 packages in 553ms

found 0 vulnerabilities

up to date, audited 2 packages in 464ms

found 0 vulnerabilities
Setting top to                           : /mnt/c/Users/pigge/OneDrive/Documents/pebble-projects/MotoMakerFace
Setting out to                           : /mnt/c/Users/pigge/OneDrive/Documents/pebble-projects/MotoMakerFace/build
Checking for program 'webpack'           : /home/lavender/.pebble-sdk/SDKs/current/node_modules/.bin/webpack
Found Pebble SDK for flint in:           : /home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/flint
Checking for program 'gcc, cc'           : arm-none-eabi-gcc
Checking for program 'ar'                : arm-none-eabi-ar
Checking if the -o link must be split from arguments : Traceback (most recent call last):
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Scripting.py", line 122, in waf_entry_point
    run_commands()
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Scripting.py", line 185, in run_commands
    ctx=run_command(cmd_name)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Scripting.py", line 176, in run_command
    ctx.execute()
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Configure.py", line 86, in execute
    super(ConfigurationContext,self).execute()
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Context.py", line 92, in execute
    self.recurse([os.path.dirname(g_module.root_path)])
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Context.py", line 133, in recurse
    user_function(self)
  File "/mnt/c/Users/pigge/OneDrive/Documents/pebble-projects/MotoMakerFace/wscript", line 23, in configure
    ctx.load('pebble_sdk')
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Configure.py", line 158, in load
    func(self)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/extras/pebble_sdk.py", line 117, in configure
    configure_platform(conf,platform)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/extras/sdk_helpers.py", line 81, in configure_platform
    ctx.load('pebble_sdk_gcc')
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Configure.py", line 158, in load
    func(self)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/extras/pebble_sdk_gcc.py", line 16, in configure
    conf.load('gcc')
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Configure.py", line 158, in load
    func(self)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Tools/gcc.py", line 104, in configure
    conf.check_gcc_o_space()
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Configure.py", line 177, in fun
    return f(*k,**kw)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Tools/c_config.py", line 802, in check_gcc_o_space
    self.check(msg='Checking if the -o link must be split from arguments',fragment=SNIP_EMPTY_PROGRAM,features=features)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Configure.py", line 177, in fun
    return f(*k,**kw)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Tools/c_config.py", line 386, in check
    ret=self.run_build(*k,**kw)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Configure.py", line 177, in fun
    return f(*k,**kw)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Configure.py", line 337, in run_build
    bld.compile()
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Build.py", line 167, in compile
    self.producer.start()
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Runner.py", line 271, in start
    self.refill_task_list()
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Runner.py", line 150, in refill_task_list
    tasks=next(self.biter)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Build.py", line 416, in get_build_iterator
    self.post_group()
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Build.py", line 362, in post_group
    tgpost(tg)
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/Build.py", line 359, in tgpost
    f()
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/TaskGen.py", line 123, in post
    v()
  File "/home/lavender/.pebble-sdk/SDKs/current/sdk-core/pebble/.waf3-2.1.4-e7919c666152db2545b931e52107c4b8/waflib/extras/pebble_sdk_common.py", line 85, in setup_pebble_c
    append_to_attr(task_gen,'includes',[lib_include_node.abspath(),lib_include_node.find_node(str(lib['name'])).find_node(platform).abspath()])
AttributeError: 'NoneType' object has no attribute 'abspath'
Build failed.

Should this work as-is?

1 Like

Ah, I might have built this on my local machine where I don’t have an sdk with flint support! That’s an easy fix though, let me push an update real quick!

3 Likes

1.0.6 wasn’t build on my computer, so it might work a bit better than 1.0.5 did! It’s already published if you want to try it

3 Likes

Dropped this into my watchface Thin, no issues so far! Thanks for taking the reigns on this one

2 Likes

Works for me, thanks.
If we can do feature requests here :smile:

  • add a property “persistPerPebble“ : true

    So we can differentiate what would be stored based as general config (for example Celcius vs Fahrenheit) and what would be stored per watch (different color themes for different watches)

  • add capabilities to the select options

    I currently need to define 2 selects for the same messageKey for different types of watches, but sometimes only a couple of options differ. This always feels like a hacky workaround.

2 Likes

Not really a request to make but a comment about something I think would be a specific optimization I would like to look to make if it’s of interest if anyone else except my one use case.

Right now one of my apps extensively uses checkboxes and they 1 take up a lot of message keys (there are 100+ and growing) and 2 are annoying to deal with. I’ve already abstracted away some of it to make it easier for me but it’d be nice if I could have a checkbox group return as a single message key and just a value of packed bytes.

It’d take me from dealing with 100+ separate message keys back from Clay to a couple encoded values like QAEACQAgABg= to parse out. I might do it anyway after vacation but I’d care more if anyone happens to think it’d improve something for them too (or if someone else does it that’s a free win for me too!)

3 Likes

Oh I love the persist per watch, but it’s going to be difficult considering that all of the settings get stored in a single local storage key. Capabilities should be a bit easier for select options.

I will have to investigate this after new years. Thank you for the suggestions!

2 Likes

You could do this now by setting autoHandleEvents: false and constructing the message yourself.

1 Like

I’ve finally taken some time to try this out. I’m using @rebble/clay at 1.0.6, SDK 4.9.77 on macOS with my default browser set to Safari.

Seems to work on my PT hardware, but in the emulator it throws and exception after a few seconds without opening the web browser.

➜ pebble emu-app-config
Traceback (most recent call last):
  File "/Users/jr/.local/bin/pebble", line 10, in <module>
    sys.exit(run_tool())
             ~~~~~~~~^^
  File "/Users/jr/.local/share/uv/tools/pebble-tool/lib/python3.13/site-packages/pebble_tool/__init__.py", line 57, in run_tool
    args.func(args)
    ~~~~~~~~~^^^^^^
  File "/Users/jr/.local/share/uv/tools/pebble-tool/lib/python3.13/site-packages/pebble_tool/commands/base.py", line 47, in <lambda>
    parser.set_defaults(func=lambda x: cls()(x))
                                       ~~~~~^^^
  File "/Users/jr/.local/share/uv/tools/pebble-tool/lib/python3.13/site-packages/pebble_tool/commands/emucontrol.py", line 109, in __call__
    response = self.pebble.read_transport_message(MessageTargetPhone, WebSocketPhonesimConfigResponse)
  File "/Users/jr/.local/share/uv/tools/pebble-tool/lib/python3.13/site-packages/libpebble2/communication/__init__.py", line 253, in read_transport_message
    return self.event_handler.wait_for_event((_EventType.Transport, origin, message_type), timeout=timeout)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jr/.local/share/uv/tools/pebble-tool/lib/python3.13/site-packages/libpebble2/events/threaded.py", line 37, in wait_for_event
    return _BlockingEventWait(self, event).wait(timeout=timeout)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/Users/jr/.local/share/uv/tools/pebble-tool/lib/python3.13/site-packages/libpebble2/events/threaded.py", line 61, in wait
    raise TimeoutError()
libpebble2.exceptions.TimeoutError
1 Like

Huh, it kinda sounds like it crashed in the emulator before you even run emu-app-config, do you get any other logs when you install the watchapp?

1 Like

The app starts normally and prints its normal log output on startup. It continues to run and update the display. When I issue the emu-app-config command from a separate terminal, no additional messages appear in the main install ... --logs output. So it seems like the problem occurs when handling the showConfiguration message in PKJS. I haven’t yet taken the time to try to instrument that side with extra logging to narrow it down.

1 Like

Couldn’t help having a go at it myself. I have a draft PR. But I wasn’t able to check the localStorage in the dev environment. I still need to test it in an actual app/watchface

1 Like

That looks pretty good! I will have a look at testing it tomorrow

1 Like

Awesome! @hellcp have you had chance to review GitHub · Where software is built and PRs?

1 Like

I looked through it at one point, but I would appreciate it if you find anything there that should be submitted to the fork and submit it. I have been investigating the branch that added a test app too!

I’ve been laying sick in bed so I’m not focusing too much on Rebble stuff today :C

1 Like

I certainly think that I could implement it locally. I just think the separate checkbox values coming back for a single group is fairly badTM no matter what though so it probably should just be the general behavior (with backwards compat surely)

The issue is if you have a growing or dynamic list of items in the checkbox group you have to reserve message keys for them going forward based on the initial group key since they’re auto assigned. For example I reserved 200 message keys for checkboxes but if I have 201 (I never will), I’ll need to shift all of the keys. This caused me to maintain a separate map of the keys based on the names so that if I do move keys around Clay can still find the right spots to inject values from old builds

Or I’m using Clay wrong and none of that is needed. But if CheckboxGroups had an option of a single value I don’t think anyone would want to use the separate key values anymore from a maintenance perspective.

1 Like

Sorry, I didn’t mean to imply that your request wasn’t a good idea. Just wanted to share some info that might help you in the meantime. I rushed my message and didn’t explain that very well.

2 Likes