Heating X2: Schedule Thermostats with Calendars [CLOSED]

Again thanks. DONE and uploaded to the repository.

What do you mean by an ‘empty template’?
Do you have blank lines in your data worksheet? You should delete any lines that do not have a thermostat name.

24 Feb 2024: Release 2.1.

Compatible with 2.0 and with same name Heating X2

This version has a more robust approach to handling the calendar to ensure that consecutive events are never missed without the need to run every minute. Now any number of overlapping events are allowed; the one with the latest start time takes precedence.

See also the thread Local Calendar feature request 5 - Recognise overlapping events

First of all: What a blueprint!!! Very nice work!!!

That being said, i’ve found a bug :slight_smile:
The setting_reason is not set on action “# ACTION[4].CHOOSE[5]. If there is no active calendar event” (line number 867). It seems the value is to long…

ps: share a 'buy me a coffee link" please :wink:

1 Like

Thank you for the kind words. I’ll look into the coffee thing :slight_smile:

It works fine in my setup but you do have to make sure the input_text.<room>_setting_reason is set to 255 characters (the maximum) as it defaults to 100, which is indeed too short (page 9 in the guide “Smart Heat Your Home with Heating X2 ”).

If you defined it in the UI, the field is “maximum length”.

If you use handmade YAML, you use the max: key, like this:

input_text:

### Kitchen heating
  kitchen_heating_setting_reason:
    name: Kitchen heating setting reason
    max: 255
    initial: “”
    icon: mdi:card-text-outline

The above is how it is defined by YAML from the code generator

I hope that helps!

1 Like

27 Feb 2024: Release 2.2.

Compatible with 2.1 and with same name Heating X2.

This release adds the option to log key events from the automations created by the blueprint into one or more log files. This helps track down anomalies like TRVs not responding correctly.

The log file content looks like this.

Heating X2 notifications (Log started: 2024-02-27T13:42:10.558298+00:00)
--------------------------------------------------------------------------------
2024-02-27T13:42:10.558335+00:00 ---
2024-02-27T13:42:10.564862+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-27T13:42:15.695047+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' set to 20.0
2024-02-27T13:42:15.703642+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' is already set to 20.0
2024-02-27T13:42:15.708166+00:00 [Parlour heating control] New state: Set manually to 20.0.
2024-02-27T13:42:20.695623+00:00 ---
2024-02-27T13:42:20.700644+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-27T13:42:20.742891+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-27T13:42:45.008107+00:00 ---
2024-02-27T13:42:45.010569+00:00 [Parlour heating control] Triggered by: echoblock_timer_end
2024-02-27T13:42:45.051430+00:00 [Parlour heating control] The thermostat 'Parlour north TRV' is set correctly.
2024-02-27T13:42:45.054353+00:00 [Parlour heating control] The thermostat 'Parlour south TRV' is set correctly.
2024-02-27T13:42:52.420332+00:00 ---
2024-02-27T13:42:52.425302+00:00 [Parlour heating control] Triggered by: manual_override_end
2024-02-27T13:43:28.606181+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' set to 21.0
2024-02-27T13:43:32.987376+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' set to 21.0
2024-02-27T13:43:32.995748+00:00 [Parlour heating control] New state: Set to 21.0 by calendar event 'Parlour Daytime' until Tue 27 Feb 2024 at 18:30.
2024-02-27T13:43:33.610287+00:00 ---
2024-02-27T13:43:33.616708+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-27T13:43:33.687466+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-27T13:43:38.188684+00:00 ---
2024-02-27T13:43:38.193401+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-27T13:43:38.234533+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-27T13:44:02.017457+00:00 ---
2024-02-27T13:44:02.021264+00:00 [Parlour heating control] Triggered by: echoblock_timer_end
2024-02-27T13:44:02.357930+00:00 [Parlour heating control] The thermostat 'Parlour north TRV' is set correctly.
2024-02-27T13:44:02.360491+00:00 [Parlour heating control] The thermostat 'Parlour south TRV' is set correctly.
2024-02-27T18:30:00.007832+00:00 ---
2024-02-27T18:30:00.009144+00:00 [Parlour heating control] Triggered by: calendar_event_end
2024-02-27T18:30:05.939880+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' set to 22.0
2024-02-27T18:30:08.989503+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' set to 22.0
2024-02-27T18:30:08.996066+00:00 [Parlour heating control] New state: Set to 22.0 by calendar event 'Parlour evening ' until Tue 27 Feb 2024 at 22:00.
2024-02-27T18:30:09.000783+00:00 ---
2024-02-27T18:30:09.005298+00:00 [Parlour heating control] Triggered by: calendar_event_start
2024-02-27T18:30:09.069108+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' is already set to 22.0
2024-02-27T18:30:09.536088+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' set to 22.0
2024-02-27T18:30:09.545442+00:00 [Parlour heating control] New state: Set to 22.0 by calendar event 'Parlour evening ' until Tue 27 Feb 2024 at 22:00.
2024-02-27T18:30:10.943223+00:00 ---
2024-02-27T18:30:10.944410+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-27T18:30:10.986450+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-27T18:30:14.128470+00:00 ---
2024-02-27T18:30:14.132698+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-27T18:30:14.175860+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-27T18:30:39.008876+00:00 ---
2024-02-27T18:30:39.010089+00:00 [Parlour heating control] Triggered by: echoblock_timer_end
2024-02-27T18:30:39.053471+00:00 [Parlour heating control] The thermostat 'Parlour north TRV' is set correctly.
2024-02-27T18:30:39.056236+00:00 [Parlour heating control] The thermostat 'Parlour south TRV' is set correctly.
2024-02-27T20:30:09.008655+00:00 ---
2024-02-27T20:30:09.015909+00:00 [Parlour heating control] Triggered by: warmup_timer_end
2024-02-27T20:30:09.089932+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' is already set to 22.0
2024-02-27T20:30:09.092705+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' is already set to 22.0
2024-02-27T20:30:09.095222+00:00 [Parlour heating control] New state: Set to 22.0 by calendar event 'Parlour evening ' until Tue 27 Feb 2024 at 22:00.
2024-02-27T22:00:00.011358+00:00 ---
2024-02-27T22:00:00.037822+00:00 [Parlour heating control] Triggered by: calendar_event_start
2024-02-27T22:00:03.420337+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' set to 12.0
2024-02-27T22:00:08.535682+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' set to 12.0
2024-02-27T22:00:08.559073+00:00 [Parlour heating control] New state: Set to 12.0 by calendar event 'Parlour Night' until Wed 28 Feb 2024 at 07:30.
2024-02-27T22:00:08.565311+00:00 ---
2024-02-27T22:00:08.569164+00:00 [Parlour heating control] Triggered by: calendar_event_end
2024-02-27T22:00:08.643776+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' is already set to 12.0
2024-02-27T22:00:30.100260+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' set to 12.0
2024-02-27T22:00:30.108363+00:00 [Parlour heating control] New state: Set to 12.0 by calendar event 'Parlour Night' until Wed 28 Feb 2024 at 07:30.
2024-02-27T22:00:30.111418+00:00 ---
2024-02-27T22:00:30.112608+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-27T22:00:30.155065+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-27T22:00:30.158329+00:00 ---
2024-02-27T22:00:30.159762+00:00 [Parlour heating control] Triggered by: warmup_timer_end
2024-02-27T22:00:30.199954+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' is already set to 12.0
2024-02-27T22:00:30.203240+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' is already set to 12.0
2024-02-27T22:00:30.205153+00:00 [Parlour heating control] New state: Set to 12.0 by calendar event 'Parlour Night' until Wed 28 Feb 2024 at 07:30.
2024-02-27T22:00:34.333885+00:00 ---
2024-02-27T22:00:34.340983+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-27T22:00:34.383639+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-27T22:01:00.011257+00:00 ---
2024-02-27T22:01:00.012819+00:00 [Parlour heating control] Triggered by: echoblock_timer_end
2024-02-27T22:01:00.055970+00:00 [Parlour heating control] The thermostat 'Parlour north TRV' is set correctly.
2024-02-27T22:01:00.058758+00:00 [Parlour heating control] The thermostat 'Parlour south TRV' is set correctly.
2024-02-28T07:30:00.015433+00:00 ---
2024-02-28T07:30:00.025182+00:00 [Parlour heating control] Triggered by: calendar_event_start
2024-02-28T07:30:04.759621+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' set to 21.0
2024-02-28T07:30:10.083307+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' set to 21.0
2024-02-28T07:30:10.098945+00:00 [Parlour heating control] New state: Set to 21.0 by calendar event 'Parlour Daytime' until Wed 28 Feb 2024 at 18:30.
2024-02-28T07:30:10.101409+00:00 ---
2024-02-28T07:30:10.102720+00:00 [Parlour heating control] Triggered by: calendar_event_end
2024-02-28T07:30:10.149496+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' is already set to 21.0
2024-02-28T07:30:10.151623+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' is already set to 21.0
2024-02-28T07:30:10.153771+00:00 [Parlour heating control] New state: Set to 21.0 by calendar event 'Parlour Daytime' until Wed 28 Feb 2024 at 18:30.
2024-02-28T07:30:10.157245+00:00 ---
2024-02-28T07:30:10.158888+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-28T07:30:10.194724+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-28T07:30:10.197321+00:00 ---
2024-02-28T07:30:10.198439+00:00 [Parlour heating control] Triggered by: warmup_timer_end
2024-02-28T07:30:10.240994+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' is already set to 21.0
2024-02-28T07:30:10.243243+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' is already set to 21.0
2024-02-28T07:30:10.246427+00:00 [Parlour heating control] New state: Set to 21.0 by calendar event 'Parlour Daytime' until Wed 28 Feb 2024 at 18:30.
2024-02-28T07:30:15.093700+00:00 ---
2024-02-28T07:30:15.094737+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-28T07:30:15.133083+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-28T07:30:40.007602+00:00 ---
2024-02-28T07:30:40.008518+00:00 [Parlour heating control] Triggered by: echoblock_timer_end
2024-02-28T07:30:40.061523+00:00 [Parlour heating control] The thermostat 'Parlour north TRV' is set correctly.
2024-02-28T07:30:40.066456+00:00 [Parlour heating control] The thermostat 'Parlour south TRV' is set correctly.
2024-02-28T18:30:00.010891+00:00 ---
2024-02-28T18:30:00.013384+00:00 [Parlour heating control] Triggered by: calendar_event_start
2024-02-28T18:30:04.206154+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' set to 22.0
2024-02-28T18:30:09.924292+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' set to 22.0
2024-02-28T18:30:09.939754+00:00 [Parlour heating control] New state: Set to 22.0 by calendar event 'Parlour evening ' until Wed 28 Feb 2024 at 22:00.
2024-02-28T18:30:09.942450+00:00 ---
2024-02-28T18:30:09.944293+00:00 [Parlour heating control] Triggered by: calendar_event_end
2024-02-28T18:30:10.008756+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' is already set to 22.0
2024-02-28T18:30:21.742637+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' set to 22.0
2024-02-28T18:30:21.757913+00:00 [Parlour heating control] New state: Set to 22.0 by calendar event 'Parlour evening ' until Wed 28 Feb 2024 at 22:00.
2024-02-28T18:30:21.764873+00:00 ---
2024-02-28T18:30:21.769632+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-28T18:30:21.826857+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-28T18:30:21.829936+00:00 ---
2024-02-28T18:30:21.831264+00:00 [Parlour heating control] Triggered by: warmup_timer_end
2024-02-28T18:30:21.872852+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' is already set to 22.0
2024-02-28T18:30:21.875211+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' is already set to 22.0
2024-02-28T18:30:21.876652+00:00 [Parlour heating control] New state: Set to 22.0 by calendar event 'Parlour evening ' until Wed 28 Feb 2024 at 22:00.
2024-02-28T18:30:21.878782+00:00 ---
2024-02-28T18:30:21.880169+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-28T18:30:21.916086+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-28T18:30:51.014656+00:00 ---
2024-02-28T18:30:51.018545+00:00 [Parlour heating control] Triggered by: echoblock_timer_end
2024-02-28T18:30:51.061281+00:00 [Parlour heating control] The thermostat 'Parlour north TRV' is set correctly.
2024-02-28T18:30:51.063501+00:00 [Parlour heating control] The thermostat 'Parlour south TRV' is set correctly.
2024-02-28T22:00:00.014070+00:00 ---
2024-02-28T22:00:00.038935+00:00 [Parlour heating control] Triggered by: calendar_event_start
2024-02-28T22:00:06.103095+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' set to 12.0
2024-02-28T22:00:13.712699+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' set to 12.0
2024-02-28T22:00:13.717110+00:00 [Parlour heating control] New state: Set to 12.0 by calendar event 'Parlour Night' until Thu 29 Feb 2024 at 07:30.
2024-02-28T22:00:13.719742+00:00 ---
2024-02-28T22:00:13.721198+00:00 [Parlour heating control] Triggered by: calendar_event_end
2024-02-28T22:00:13.765074+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' is already set to 12.0
2024-02-28T22:00:16.449866+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' set to 12.0
2024-02-28T22:00:16.454016+00:00 [Parlour heating control] New state: Set to 12.0 by calendar event 'Parlour Night' until Thu 29 Feb 2024 at 07:30.
2024-02-28T22:00:16.456211+00:00 ---
2024-02-28T22:00:16.458077+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-28T22:00:16.496773+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-28T22:00:16.499232+00:00 ---
2024-02-28T22:00:16.500812+00:00 [Parlour heating control] Triggered by: warmup_timer_end
2024-02-28T22:00:16.540195+00:00 [Parlour heating control] Thermostat 'Parlour north TRV' is already set to 12.0
2024-02-28T22:00:16.542812+00:00 [Parlour heating control] Thermostat 'Parlour south TRV' is already set to 12.0
2024-02-28T22:00:16.544741+00:00 [Parlour heating control] New state: Set to 12.0 by calendar event 'Parlour Night' until Thu 29 Feb 2024 at 07:30.
2024-02-28T22:00:21.082915+00:00 ---
2024-02-28T22:00:21.084223+00:00 [Parlour heating control] Triggered by: set_temperature_change
2024-02-28T22:00:21.130322+00:00 [Parlour heating control] Set temperature ignored during echo block period
2024-02-28T22:00:46.015276+00:00 ---
2024-02-28T22:00:46.019413+00:00 [Parlour heating control] Triggered by: echoblock_timer_end
2024-02-28T22:00:46.058860+00:00 [Parlour heating control] The thermostat 'Parlour north TRV' is set correctly.
2024-02-28T22:00:46.061249+00:00 [Parlour heating control] The thermostat 'Parlour south TRV' is set correctly.

By default logging is turned off. See the updated guide “Smart Heat Your Home with Heating X2 (v2.2)” (bundled with the code generator) for details of how to set up logging.

Thx, I should have read the **** manual :slight_smile:

1 Like

You need to optimize the blueprint optic :see_no_evil:

What do you mean by ‘blueprint optic’?

The Look of the blueprint, to overload in first look in my oppinion.

Check Cover Control or advanced heating

1 Like

Indeed the deletion of empty lines helps - ignore my issue :slight_smile:

1 Like

It is a large blueprint (over 1000 lines now) and precisely for that reason I have laid it out to be easily legible (for me). Of course you can delete blank lines and comments if you wish, but I do not see how that is an improvement? :thinking:

What I have done in an effort to improve comprehensibility is add an overview in the comments at the start of the file:

### OVERVIEW 
### The main action steps are as follows. 
### The numbering correspnds to that used by the system log for error messages.  
### ACTION[0] -- LOG THE TRIGGER. Starts a new log file entry by writing a bank line and the trigger id 
### ACTIONS[1-3] -- FETCH THE CURRENT AND NEXT CALENDAR EVENTS 
###              Calls calendar.get_events twice, then sets local variables for later use 
### ACTION[4] -- RESPOND TO TRIGGERS WHERE NECESSARY. A big choose statement on the trigger_id. 
### ACTION[5] -- DETERMINE THE REQUIRED TEMPERATURE ACCORDING TO THE STATE. A big chooose statement on the relevant states variables.
###              Decides what teperature is required and why. Sets the 'required temperature' helper and the 'reason test' helper. 
### ACTION[6] -- SEND TEMPERATURE CHANGE TO THE THERMOSTATS
###              Loops through all the thermostats for the room. If the required temperature is 
###              different from the actual one, the service call to change it is invoked and the echoblock (response timerout) timer started. 
### ACTION[7] -- LOG THE REASON. Writes the last line of the log file entry 

You also get a nice picture of how it works if you look at the trace of one of the automations that use it.

Does that help?

… nevertheless, for anyone else who misses this, I have now added code to check whether the max length is set to 255 before attempting to write anything. If it is less than 255, an error messge is written to the ‘setting reason’ instead. :upside_down_face:

Minor updates to version 2.2.

None of these affect the basic functionality. Following a period of beta-testing, measures are taken to increase robustness in case of device failures and anomalies, i.e. avoid automation failures and system log errors, improve notifications and logging.

  • 01-Mar-2024: 2.2.01. Code added to check that the ‘setting reason’ input_text helper has a max length of 255 characters. Default is 100, which is too short. If not set to 255, an error message is written into the ‘setting reason’.
  • 02-Mar-2024: 2.2.02. Added an id to the away_switch_on and _off triggers, now separated, for logging purposes
  • 05-Mar-2024: 2.2.03. Added detail to the trigger line of the log entries
  • 08-Mar-2024: 2.2.04. Correct trigger line of the log entries when calendar event triggers have no entity_id
  • 09-Mar-2024: 2.2.05. Tidied up logic of ACTION[6] using choose, to ensure there is always a log message
  • 09-Mar-2024: 2.2.06. Warmup timer reset only if nothing is scheduled (previously sometimes premature with consecutive events)
  • 09-Mar-2024: 2.2.07. Improved notifications. Additional unknown and offline every time a setting is needed. Dismissed when online. Only ever one notification per device.
  • 09-Mar-2024: 2.2.08. Now ignores false ‘set temperature change’ from a device when it goes unavailable, and other out of range (false) temperature settings
  • 13-Mar-2024: 2.2.09. Added ‘continue_on_error’ and ‘parallel’ to thermostat service call, ‘continue_on_error’ to logs and notifications to better cope with device errors
  • 14-Mar-2024: 2.2.10 Thermostat available trigger time increased and now resets manual override, because sometimes TRVs go offline for just a few seconds (might be a ZHA glitch?)
1 Like

This is just superb - thank you so much! One suggestion to make it even better - how about introducing a dynamic warmup time per zone, like some systems such as Honeywell Evohome do? @tommypearse looks to have done a lot of hard work in that department here: Optimum Start for Heating Systems, or alternatively something that uses statistics from logs of previous heat up times as a guide, maybe even something that’s influenced by the weather too?

1 Like

Sounds like a great idea. I do not know the Honeywell system, but I guess you mean you want to set the time the room needs to be warm and have the system calculate an earlier time to actually turn it on?

At the moment, my warmup time starts at the calendar start time and all it does is to tell the automation to ignore the fact that the room is unoccupied.

Yes that’s exactly right - I think it has calculations based on how long it’s taken over previous days to heat a room up and uses it to work out when it needs to begin heating to get to the desired target temperature at the specified time. It could even be used in conjunction with the method I linked above to work out the expected heat loss for a room (as an option only for people who want to go to the effort of punching in all the relevant data for each room!)
Weather compensation is also worth considering too - so based on either the weather forecast or an outdoor temperature sensor, increase or decrease the warmup time accordingly.
I imagine it’s a pretty complex thing to work out though, and is probably something that would require a lot of testing and tweaking!

Mmm. So it is a substantial change. I think the way I would approach it is

  1. set up [room]_warmup_time as an input_time variable for each room (instead of a constant, as now)
  2. using whatever algorithm you have – based on past data perhaps with outside temperature and weather forecast – give it a value every day in a separate automation
  3. modify the calendar event start trigger in the blueprint with a negative offset so that it starts at the calendar time minus the [room]_warmup_time.
  4. start the [room]_warmup_timer (to ignore presence) using [room]_warmup_time as its start value.

If you want to show off, you could do the converse with a ‘cool down’ time that turns the heating off a little before you plan to vacate the room.

Do let me know if you get it working!

If this blueprint was of use to you. please buy me a coffee!

Hi @AndySymons. I’ve been using Schedy Schedule via AppDaemon to control my 3-zone heating and hot water system for a few years. It’s been working well, but I’ve been on the lookout for a more graphical way of scheduling my heating and came across your projects. They look great & I’ve followed your installation guides, however I’m getting an error when I run a test Y2 schedule saying that my automation “has an action that calls an unknown service: script.heating_xyz_logfile_entry”.
I have a scripts.yaml file and have also included script: !include scripts.yaml in my main configuration.yaml.
One thing that I have noticed is that the logfile_entry_script-yaml on your github calls for a script logfile_entry:, whereas the Y2 automation calls for service: script.heating_xyz_logfile_entry.
I tried renaming the script from logfile_entry to heating_xyz_logfile_entry but I still get the same error.
Any suggestions what I’m doing wrong? Cheers, Craig